﻿///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2023, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

#Область ПрограммныйИнтерфейс

////////////////////////////////////////////////////////////////////////////////
// Добавление, изменение и получение контактной информации.

// Возвращает таблицу, содержащую контактную информацию нескольких объектов. 
//
// Параметры:
//    Источник         - Массив - владельцы контактной информации.
//    Отбор - см. ОтборКонтактнойИнформации.
//
// Возвращаемое значение:
//  ТаблицаЗначений:
//   * Объект           - ЛюбаяСсылка - владелец контактной информации.
//   * Вид              - СправочникСсылка.ВидыКонтактнойИнформации - вид контактной информации.
//   * Тип              - ПеречислениеСсылка.ТипыКонтактнойИнформации - тип контактной информации.
//   * Значение         - Строка - контактная информация во внутреннем формате JSON.
//   * Представление    - Строка - представление контактной информации.
//   * Дата             - Дата   - дата, с которой действует запись контактной информации.
//   * ИдентификаторСтрокиТабличнойЧасти - Число - идентификатор строки этой табличной части
//   * ЗначенияПолей    - Строка - устаревший XML, соответствующий XDTO пакетам КонтактнаяИнформация или Адрес. Для
//                                 обратной совместимости.
//
Функция КонтактнаяИнформация(Источник, Отбор) Экспорт
	
	КонтактнаяИнформацияОбъекты = Новый Массив; // Массив из СправочникОбъект
	КонтактнаяИнформацияСсылки  = Новый Массив;
	
	Если ТипЗнч(Источник) = Тип("Массив") Тогда
		СсылкиИлиОбъекты = Источник;
	Иначе
		СсылкиИлиОбъекты = ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(Источник);
	КонецЕсли;
	
	Для Каждого СсылкаИлиОбъект Из СсылкиИлиОбъекты Цикл
		
		Если ОбщегоНазначения.ЭтоСсылка(ТипЗнч(СсылкаИлиОбъект)) Тогда
			КонтактнаяИнформацияСсылки.Добавить(СсылкаИлиОбъект);
		Иначе
			КонтактнаяИнформацияОбъекты.Добавить(СсылкаИлиОбъект);
		КонецЕсли;
		
	КонецЦикла;
	
	Дата = Отбор.Дата;
	
	ТипыКонтактнойИнформации = Неопределено;
	Если ЗначениеЗаполнено(Отбор.ТипыКонтактнойИнформации) Тогда
		ТипыКонтактнойИнформации = Отбор.ТипыКонтактнойИнформации;
		
		Если ТипЗнч(ТипыКонтактнойИнформации) = Тип("ПеречислениеСсылка.ТипыКонтактнойИнформации") Тогда
			ТипыКонтактнойИнформации = ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(ТипыКонтактнойИнформации);
		КонецЕсли;
	КонецЕсли;
	
	ВидыКонтактнойИнформации = Неопределено;
	Если ЗначениеЗаполнено(Отбор.ВидыКонтактнойИнформации) Тогда
		ВидыКонтактнойИнформации = Отбор.ВидыКонтактнойИнформации;
		
		Если ТипЗнч(ВидыКонтактнойИнформации) = Тип("СправочникСсылка.ВидыКонтактнойИнформации") Тогда
			ВидыКонтактнойИнформации = ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(ВидыКонтактнойИнформации);
		КонецЕсли;
	КонецЕсли;
	
	Результат = НоваяКонтактнаяИнформация(Истина);
	
	Если КонтактнаяИнформацияСсылки.Количество() > 0 Тогда
		
		Запрос = Новый Запрос;
		Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
		
		СоздатьВТКонтактнаяИнформация(Запрос.МенеджерВременныхТаблиц, КонтактнаяИнформацияСсылки, ТипыКонтактнойИнформации, ВидыКонтактнойИнформации, Дата);
		
		ДействуетС = ?(ТипЗнч(Дата) = Тип("Дата"), "КонтактнаяИнформация.ДействуетС", "ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0)");
		
		Запрос.Текст =
		"ВЫБРАТЬ
		|	КонтактнаяИнформация.Объект КАК Объект,
		|	КонтактнаяИнформация.Вид КАК Вид,
		|	КонтактнаяИнформация.Тип КАК Тип,
		|	КонтактнаяИнформация.Значение КАК Значение,
		|	КонтактнаяИнформация.ЗначенияПолей КАК ЗначенияПолей,
		|	КонтактнаяИнформация.НомерСтроки КАК НомерСтроки,
		|	КонтактнаяИнформация.ИдентификаторСтрокиТабличнойЧасти КАК ИдентификаторСтрокиТабличнойЧасти,
		|	&ДействуетС КАК Дата,
		|	КонтактнаяИнформация.Представление КАК Представление
		|ИЗ
		|	ВТКонтактнаяИнформация КАК КонтактнаяИнформация
		|
		|УПОРЯДОЧИТЬ ПО
		|	НомерСтроки";
		
		Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ДействуетС", ДействуетС);
		
		РезультатСсылка = Запрос.Выполнить().Выгрузить();
		
		Для каждого СтрокаКонтактнойИнформации Из РезультатСсылка Цикл
			
			НоваяСтрока = Результат.Добавить();
			ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаКонтактнойИнформации);
			
			Если ПустаяСтрока(НоваяСтрока.Значение)
				И ЗначениеЗаполнено(НоваяСтрока.ЗначенияПолей) Тогда
				НоваяСтрока.Значение = КонтактнаяИнформацияВJSON(НоваяСтрока.ЗначенияПолей, НоваяСтрока.Тип);
			КонецЕсли;
		КонецЦикла;
		
	КонецЕсли;
	
	Для Каждого КонтактнаяИнформацияОбъект Из КонтактнаяИнформацияОбъекты Цикл
		
		Если СодержитКонтактнуюИнформацию(ТипЗнч(КонтактнаяИнформацияОбъект)) Тогда
			
			Для каждого СтрокаКонтактнойИнформации Из КонтактнаяИнформацияОбъект.КонтактнаяИнформация Цикл
				
				Если Не ЗначениеЗаполнено(СтрокаКонтактнойИнформации.Вид) Тогда
					Продолжить;
				КонецЕсли;
				
				Если УправлениеКонтактнойИнформациейСлужебныйПовтИсп.КонтактнаяИнформацияОбъектаСодержитКолонкуДействуетС(КонтактнаяИнформацияОбъект.Ссылка) Тогда
					
					Если СтрокаКонтактнойИнформации.ДействуетС > Дата Тогда
						Продолжить;
					КонецЕсли;
					
					ФильтрПоДате = Новый Структура;
					ФильтрПоДате.Вставить("Объект", КонтактнаяИнформацияОбъект);
					ФильтрПоДате.Вставить("Вид",    СтрокаКонтактнойИнформации.Вид);
					
					НайденныеСтроки = Результат.НайтиСтроки(ФильтрПоДате);
					
					Если НайденныеСтроки.Количество() > 0 Тогда
						Если НайденныеСтроки[0].Дата < СтрокаКонтактнойИнформации.ДействуетС Тогда
							Результат.Удалить(НайденныеСтроки[0]);
						Иначе
							Продолжить;
						КонецЕсли;
					КонецЕсли;
					
				КонецЕсли;
				
				Если (ТипыКонтактнойИнформации = Неопределено Или ТипыКонтактнойИнформации.Найти(СтрокаКонтактнойИнформации.Тип) <> Неопределено)
					И (ВидыКонтактнойИнформации = Неопределено Или ВидыКонтактнойИнформации.Найти(СтрокаКонтактнойИнформации.Вид) <> Неопределено) Тогда
					
					НоваяСтрока = Результат.Добавить();
					ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаКонтактнойИнформации);
					
					НоваяСтрока.Объект = КонтактнаяИнформацияОбъект;
					
					Если ПустаяСтрока(НоваяСтрока.Значение)
						И ЗначениеЗаполнено(НоваяСтрока.ЗначенияПолей) Тогда
						НоваяСтрока.Значение = КонтактнаяИнформацияВJSON(НоваяСтрока.ЗначенияПолей, НоваяСтрока.Тип);
					КонецЕсли;
					
					Если УправлениеКонтактнойИнформациейСлужебныйПовтИсп.КонтактнаяИнформацияОбъектаСодержитКолонкуДействуетС(КонтактнаяИнформацияОбъект.Ссылка) Тогда
						НоваяСтрока.Дата = СтрокаКонтактнойИнформации.ДействуетС;
					КонецЕсли;
					
				КонецЕсли;
			КонецЦикла;
			
		КонецЕсли;
	КонецЦикла;
	
	КодЯзыка = СтрРазделить(Отбор.КодЯзыка, "_", Истина)[0];
	Если ЗначениеЗаполнено(КодЯзыка) И КодЯзыка <> ОбщегоНазначения.КодОсновногоЯзыка() Тогда
		Для Каждого СтрокаТаблицы Из Результат Цикл
			Если СтрокаТаблицы.Тип = Перечисления.ТипыКонтактнойИнформации.Адрес Тогда
				СтрокаТаблицы.Представление = СтроковыеФункции.СтрокаЛатиницей(СтрокаТаблицы.Представление);
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Конструктор параметра Отбор для функции КонтактнаяИнформация.
//
// Возвращаемое значение:
//  Структура:
//   * ТипыКонтактнойИнформации - Массив из ПеречислениеСсылка.ТипыКонтактнойИнформации - отбор по типу контактной информации.
//   * ВидыКонтактнойИнформации - Массив из СправочникСсылка.ВидыКонтактнойИнформации - отбор по видам контактной информации.
//   * Дата                     - Дата - дата с которой действует запись контактной информации, используется при хранении
//                                       истории изменения контактной информации. Если владелец хранит историю изменений,
//                                       то при несоответствии параметра дате будет вызвано исключение.
//   * КодЯзыка - Строка - код языка, на котором необходимо получить представление контактной информации.
//                         Представления контактной информации типа Адрес будет получено путем транслитерации, на остальные
//                         типы контактной информации данных параметр не влияет.
//
Функция ОтборКонтактнойИнформации() Экспорт
	
	Отбор = Новый Структура;
	Отбор.Вставить("ТипыКонтактнойИнформации", Новый Массив);
	Отбор.Вставить("ВидыКонтактнойИнформации", Новый Массив);
	Отбор.Вставить("Дата");
	Отбор.Вставить("КодЯзыка");
	
	Возврат Отбор;
	
КонецФункции

// Возвращает таблицу, содержащую контактную информацию нескольких объектов. 
//
// Параметры:
//    СсылкиИлиОбъекты         - Массив - владельцы контактной информации.
//    ТипыКонтактнойИнформации - Массив
//                             - ПеречислениеСсылка.ТипыКонтактнойИнформации - если указаны, то будет получена
//        контактная информация только этих типов.
//    ВидыКонтактнойИнформации - Массив
//                             - СправочникСсылка.ВидыКонтактнойИнформации - если указаны, то будет возвращена
//                               контактная информация только этих видов контактной информации.
//    Дата                     - Дата   - дата с которой действует запись контактной информации,
//                              используется при хранении истории изменения контактной информации.
//                              Если владелец хранит историю изменений, то при несоответствии параметра
//                              дате будет вызвано исключение.
//
// Возвращаемое значение:
//  ТаблицаЗначений:
//    * Объект           - ЛюбаяСсылка - владелец контактной информации.
//    * Вид              - СправочникСсылка.ВидыКонтактнойИнформации - вид контактной информации.
//    * Тип              - ПеречислениеСсылка.ТипыКонтактнойИнформации - тип контактной информации.
//    * Значение         - Строка - контактная информация во внутреннем формате JSON.
//    * Представление    - Строка - представление контактной информации.
//    * Дата             - Дата - дата, с которой действует запись контактной информации.
//    * ИдентификаторСтрокиТабличнойЧасти - Число - идентификатор строки этой табличной части
//    * ЗначенияПолей    - Строка - устаревший XML, соответствующий XDTO пакетам КонтактнаяИнформация или Адрес. Для
//                                  обратной совместимости.
//
Функция КонтактнаяИнформацияОбъектов(СсылкиИлиОбъекты, Знач ТипыКонтактнойИнформации = Неопределено, Знач ВидыКонтактнойИнформации = Неопределено, Дата = Неопределено) Экспорт
	
	Отбор = ОтборКонтактнойИнформации();
	
	Если ТипЗнч(ТипыКонтактнойИнформации) = Тип("Массив") Тогда
		Отбор.ТипыКонтактнойИнформации = ТипыКонтактнойИнформации;
	ИначеЕсли ЗначениеЗаполнено(ТипыКонтактнойИнформации) Тогда
		Отбор.ТипыКонтактнойИнформации.Добавить(ТипыКонтактнойИнформации);
	КонецЕсли;
	
	Если ТипЗнч(ВидыКонтактнойИнформации) = Тип("Массив") Тогда
		Отбор.ВидыКонтактнойИнформации = ВидыКонтактнойИнформации;
	ИначеЕсли ЗначениеЗаполнено(ВидыКонтактнойИнформации) Тогда
		Отбор.ВидыКонтактнойИнформации.Добавить(ВидыКонтактнойИнформации);
	КонецЕсли;
	
	Отбор.Дата = Дата;
	
	Возврат КонтактнаяИнформация(СсылкиИлиОбъекты, Отбор);
	
КонецФункции

// Возвращает таблицу, содержащую контактную информацию объекта.
// Поведение, при котором возвращалось представление контактной информации, теперь считается устаревшим
// и сохранено для обратной совместимости. Для получения представления контактной информации рекомендуется
// использовать функцию ПредставлениеКонтактнойИнформацииОбъекта.
//
// Параметры:
//  СсылкаИлиОбъект - ОпределяемыйТип.ВладелецКонтактнойИнформации
//                  - СправочникОбъект
//                  - ДокументОбъект - ссылка или объект-владелец контактной информации (организация,
//                                      контрагент, партнер и т.д.).
//  ВидИлиТипКонтактнойИнформации - СправочникСсылка.ВидыКонтактнойИнформации - отбор по виду контактной информации.
//                                - ПеречислениеСсылка.ТипыКонтактнойИнформации - отбор по типу контактной информации.
//  Дата                     - Дата - дата с которой действует запись контактной информации,
//                              используется при хранении истории изменения контактной информации.
//                              Если владелец хранит историю изменений, то при несоответствии параметра
//                              дате будет вызвано исключение.
//  ТолькоПредставление      - Булево - если Истина, то возвращает только представление, иначе таблицу значений.
//                                      Для получения представления рекомендуется использовать функцию ПредставлениеКонтактнойИнформацииОбъекта.
// 
// Возвращаемое значение:
//  ТаблицаЗначений:
//    * Объект           - ЛюбаяСсылка - владелец контактной информации.
//    * Вид              - СправочникСсылка.ВидыКонтактнойИнформации   - вид контактной информации.
//    * Тип              - ПеречислениеСсылка.ТипыКонтактнойИнформации - тип контактной информации.
//    * Значение         - Строка - контактная информация во внутреннем формате JSON.
//    * Представление    - Строка - представление контактной информации.
//    * Дата             - Дата   - дата, с которой действует запись контактной информации.
//    * ИдентификаторСтрокиТабличнойЧасти - Число - идентификатор строки этой табличной части
//    * ЗначенияПолей    - Строка - устаревший XML, соответствующий XDTO пакетам КонтактнаяИнформация или Адрес. Для
//                                  обратной совместимости.
//
Функция КонтактнаяИнформацияОбъекта(СсылкаИлиОбъект, ВидИлиТипКонтактнойИнформации = Неопределено, Дата = Неопределено, ТолькоПредставление = Истина) Экспорт
	
	ТипКонтактнойИнформации = Неопределено;
	ВидКонтактнойИнформации = Неопределено;
	Если ТипЗнч(ВидИлиТипКонтактнойИнформации) = Тип("ПеречислениеСсылка.ТипыКонтактнойИнформации") Тогда
		ТипКонтактнойИнформации = ВидИлиТипКонтактнойИнформации;
	ИначеЕсли ТипЗнч(ВидИлиТипКонтактнойИнформации) = Тип("СправочникСсылка.ВидыКонтактнойИнформации") Тогда
		ВидКонтактнойИнформации = ВидИлиТипКонтактнойИнформации;
	КонецЕсли;
	
	ТипОбъекта = ТипЗнч(СсылкаИлиОбъект);
	Если НЕ ОбщегоНазначения.ЭтоСсылка(ТипОбъекта) Тогда
		
		Результат = НоваяКонтактнаяИнформация();
		Если СодержитКонтактнуюИнформацию(ТипОбъекта) Тогда
			
			Для каждого СтрокаКонтактнойИнформации Из СсылкаИлиОбъект.КонтактнаяИнформация Цикл
				Если ВидИлиТипКонтактнойИнформации = Неопределено
					ИЛИ СтрокаКонтактнойИнформации.Тип = ТипКонтактнойИнформации
					ИЛИ СтрокаКонтактнойИнформации.Вид = ВидКонтактнойИнформации Тогда
						НоваяСтрока = Результат.Добавить();
						ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаКонтактнойИнформации);
						Если ПустаяСтрока(НоваяСтрока.Значение)
							 И ЗначениеЗаполнено(НоваяСтрока.ЗначенияПолей) Тогда
								НоваяСтрока.Значение = КонтактнаяИнформацияВJSON(НоваяСтрока.ЗначенияПолей, СтрокаКонтактнойИнформации.Тип);
						КонецЕсли;
						НоваяСтрока.Объект = СсылкаИлиОбъект;
				КонецЕсли;
			КонецЦикла;
			
		КонецЕсли;
		
		Если ТолькоПредставление Тогда
			Если Результат.Количество() > 0 Тогда
				Возврат Результат[0].Представление;
			КонецЕсли;
			Возврат "";
		КонецЕсли;
		
		Возврат Результат;
		
	КонецЕсли;
	
	Если ТолькоПредставление Тогда
		// Оставлено для обратной совместимости.
		МассивОбъектов = Новый Массив;
		МассивОбъектов.Добавить(СсылкаИлиОбъект.Ссылка);
		
		Если НЕ ЗначениеЗаполнено(ВидИлиТипКонтактнойИнформации) Тогда
			Возврат "";
		КонецЕсли;
		
		КонтактнаяИнформацияОбъекта = КонтактнаяИнформацияОбъектов(МассивОбъектов, ТипКонтактнойИнформации, ВидКонтактнойИнформации, Дата);
		
		Если КонтактнаяИнформацияОбъекта.Количество() > 0 Тогда
			Возврат КонтактнаяИнформацияОбъекта[0].Представление;
		КонецЕсли;
		
		Возврат "";
	Иначе
		СсылкиИлиОбъекты = Новый Массив;
		СсылкиИлиОбъекты.Добавить(СсылкаИлиОбъект);
		
		Если ТипКонтактнойИнформации <> Неопределено Тогда
			ТипыКонтактнойИнформации = Новый Массив;
			ТипыКонтактнойИнформации.Добавить(ТипКонтактнойИнформации);
			ВидыКонтактнойИнформации = Неопределено;
		ИначеЕсли ВидКонтактнойИнформации <> Неопределено Тогда
			ВидыКонтактнойИнформации = Новый Массив;
			ВидыКонтактнойИнформации.Добавить(ВидКонтактнойИнформации);
			ТипыКонтактнойИнформации = Новый Массив;
			ТипыКонтактнойИнформации.Добавить(ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ВидКонтактнойИнформации, "Тип"));
		Иначе
			ТипыКонтактнойИнформации = Неопределено;
			ВидыКонтактнойИнформации = Неопределено;
		КонецЕсли;
		
		Возврат КонтактнаяИнформацияОбъектов(СсылкиИлиОбъекты, ТипыКонтактнойИнформации, ВидыКонтактнойИнформации, Дата);
	КонецЕсли;
	
КонецФункции

// Возвращает представление контактной информации объекта.
//
// Параметры:
//  СсылкаИлиОбъект         - Произвольный - владелец контактной информации.
//  ВидКонтактнойИнформации - СправочникСсылка.ВидыКонтактнойИнформации - вид контактной информации.
//  Разделитель             - Строка - разделитель, который добавляется в представление между записями контактной информации.
//                                     По умолчанию это запятая с последующим пробелом, для исключения
//                                     пробела необходимо использовать признак БезПробелов у параметра ДополнительныеПараметры.
//  Дата                    - Дата - дата, с которой действует запись контактной информации. Если контактная информация
//                                   хранит историю изменения, то передача даты обязательна.
//  ДополнительныеПараметры - Структура - необязательные параметры для формирования представления контактной информации:
//   * ТолькоПервая         - Булево - если Истина, то будет возвращено представление только основной(первой) записи
//                                     контактной информации. По умолчанию - Ложь;
//   * БезПробелов          - Булево - если Истина, то после разделителя не будет автоматически добавляться пробел.
//                                     По умолчанию - Ложь;
// 
// Возвращаемое значение:
//  Строка
//
Функция ПредставлениеКонтактнойИнформацииОбъекта(СсылкаИлиОбъект, ВидКонтактнойИнформации, Разделитель = ",", Дата = Неопределено, ДополнительныеПараметры = Неопределено) Экспорт
	
	ТолькоПервая = Ложь;
	БезПробелов = Ложь;
	Если ТипЗнч(ДополнительныеПараметры) = Тип("Структура") Тогда
		Если ДополнительныеПараметры.Свойство("ТолькоПервая") Тогда
			ТолькоПервая = ДополнительныеПараметры.ТолькоПервая;
		КонецЕсли;
		Если ДополнительныеПараметры.Свойство("БезПробелов") Тогда
			БезПробелов = ДополнительныеПараметры.БезПробелов;
		КонецЕсли;
	КонецЕсли;
	РазделительВПредставлении = ?(БезПробелов, Разделитель, Разделитель + " ");
	
	ПервыйПроход         = Истина;
	КонтактнаяИнформация = КонтактнаяИнформацияОбъекта(СсылкаИлиОбъект, ВидКонтактнойИнформации, Дата, Ложь);
	
	Если ТипЗнч(КонтактнаяИнформация) = Тип("ТаблицаЗначений") Тогда
		
		Для каждого ЗаписьКонтактнойИнформации Из КонтактнаяИнформация Цикл
			Если ПервыйПроход Тогда
				Представление = ЗаписьКонтактнойИнформации.Представление;
				Если ТолькоПервая Тогда
					Возврат Представление;
				КонецЕсли;
				ПервыйПроход = Ложь;
			Иначе
				Представление = Представление + РазделительВПредставлении + ЗаписьКонтактнойИнформации.Представление;
			КонецЕсли;
		КонецЦикла;
		
	Иначе
		
		Представление = КонтактнаяИнформация;
		
	КонецЕсли;
	
	Возврат Представление;
	
КонецФункции

// Формирует новую таблицу контактной информации.
//
// Параметры:
//  КолонкаОбъект - Булево - если Истина, то таблица будет содержать колонку "Объект".
//                           Это нужно, если в таблице необходимо хранить контактной информацию для нескольких объектов.
// 
// Возвращаемое значение:
//  ТаблицаЗначений:
//       * Объект        - ЛюбаяСсылка - владелец контактной информации.
//       * Вид           - СправочникСсылка.ВидыКонтактнойИнформации - вид контактной информации.
//       * Тип           - ПеречислениеСсылка.ТипыКонтактнойИнформации - тип контактной информации.
//       * Значение      - Строка - JSON, соответствующий структуре контактной информации.
//       * ЗначенияПолей - Строка - XML, соответствующий XDTO пакету КонтактнаяИнформация или Адрес.
//       * Представление - Строка - представление контактной информации.
//       * Дата          - Дата   - дата, с которой действует запись контактной информации.
//       * ИдентификаторСтрокиТабличнойЧасти - Число - идентификатор строки этой табличной части
//
Функция НоваяКонтактнаяИнформация(КолонкаОбъект = Истина) Экспорт
	
	КонтактнаяИнформация = Новый ТаблицаЗначений;
	ОписаниеТиповСтрока1500 = Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(1500));
	
	Если КолонкаОбъект Тогда
		КонтактнаяИнформация.Колонки.Добавить("Объект");
	КонецЕсли;
	
	КонтактнаяИнформация.Колонки.Добавить("Представление",                     ОписаниеТиповСтрока1500);
	КонтактнаяИнформация.Колонки.Добавить("ЗначенияПолей",                     Новый ОписаниеТипов("Строка"));
	КонтактнаяИнформация.Колонки.Добавить("Значение",                          Новый ОписаниеТипов("Строка"));
	КонтактнаяИнформация.Колонки.Добавить("Вид",                               Новый ОписаниеТипов("СправочникСсылка.ВидыКонтактнойИнформации"));
	КонтактнаяИнформация.Колонки.Добавить("Тип",                               Новый ОписаниеТипов("ПеречислениеСсылка.ТипыКонтактнойИнформации"));
	КонтактнаяИнформация.Колонки.Добавить("Дата",                              Новый ОписаниеТипов("Дата"));
	КонтактнаяИнформация.Колонки.Добавить("ИдентификаторСтрокиТабличнойЧасти", Новый ОписаниеТипов("Число"));
	
	Возврат КонтактнаяИнформация;
	
КонецФункции

// Добавляет контактную информацию к объекту по представлению или JSON.
//
// Параметры:
//  СсылкаИлиОбъект - СправочникСсылка
//                  - ДокументСсылка
//                  - СправочникОбъект
//                  - ДокументОбъект - ссылка или объект владельца
//                                     содержащего контактную информацию. Для ссылки после добавления контактной
//                                     информации владелец будет записан. Если передан объект, то контактная
//                                     информация будет добавлена без записи. Для сохранения изменений объект
//                                     необходимо будет записать отдельно.
//  ЗначениеИлиПредставление - Строка - представление, JSON или XML соответствующее XDTO-пакету КонтактнаяИнформация
//                                      или Адрес.
//  ВидКонтактнойИнформации  - СправочникСсылка.ВидыКонтактнойИнформации - вид добавляемой контактной информации.
//  Дата                     - Дата    - дата, с которой будет действовать запись контактной информации.
//                                       Требуется для контактной информации, у которой хранится история изменений.
//                                       Если значение не указано, то принимается текущая дата сеанса.
//  Замещать                 - Булево - если Истина(по умолчанию), то будет заменена вся контактная информация по
//                                      переданному виду контактной информации.
//                                      Если Ложь, то запись будет добавлена. Если вид контактной информации не разрешает
//                                      ввод нескольких значений, а контактная информация объекта уже содержит запись,
//                                      то запись не будет добавлена.
//
Процедура ДобавитьКонтактнуюИнформацию(СсылкаИлиОбъект, ЗначениеИлиПредставление, ВидКонтактнойИнформации, Дата = Неопределено, Замещать = Истина) Экспорт
	
	Если ОбщегоНазначения.ЭтоСсылка(ТипЗнч(СсылкаИлиОбъект)) Тогда
		УправлениеКонтактнойИнформациейСлужебный.ДобавитьКонтактнуюИнформациюДляСсылки(СсылкаИлиОбъект,
			ЗначениеИлиПредставление, ВидКонтактнойИнформации, Дата, Замещать);
		Возврат;
	КонецЕсли;
	
	УправлениеКонтактнойИнформациейСлужебный.ДобавитьКонтактнуюИнформацию(СсылкаИлиОбъект, ЗначениеИлиПредставление, 
		ВидКонтактнойИнформации, Дата, Замещать);
	
КонецПроцедуры

// Добавляет или изменяет контактную информацию для нескольких владельцев контактной информации.
// Важно! Если в колонке Объект у параметра КонтактнаяИнформация указана ссылка, то после добавления
// контактной информации владелец будет записан. В случае, если колонка Объект содержит объект владельца
// контактной информации, то для сохранения изменений объекты необходимо будет записать отдельно.
//
// Параметры:
//  КонтактнаяИнформация - см. УправлениеКонтактнойИнформацией.НоваяКонтактнаяИнформация
//  Замещать             - Булево -  если Истина(по умолчанию), то будет заменена вся
//                                   вся контактная информация по переданном виду контактной информации.
//                                   Если Ложь, то запись будет добавлена. Если вид контактной информации не разрешает
//                                   ввод нескольких значений, а контактная информация объекта уже содержит запись,
//                                   то запись не будет добавлена.
//                                   
//                                   
//
Процедура УстановитьКонтактнуюИнформациюОбъектов(КонтактнаяИнформация, Замещать = Истина) Экспорт
	
	Если КонтактнаяИнформация.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;
	
	ВладельцыКонтактнойИнформации = Новый Соответствие;
	Для каждого СтрокаКонтактнойИнформации Из КонтактнаяИнформация Цикл
		ПараметрыКонтактнойИнформации = ВладельцыКонтактнойИнформации[СтрокаКонтактнойИнформации.Объект];
		Если ПараметрыКонтактнойИнформации = Неопределено Тогда
			Если Не СодержитКонтактнуюИнформацию(СтрокаКонтактнойИнформации.Объект) Тогда
				ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( 
					НСтр("ru = 'Объект %1 не подключен к подсистеме ""Контактная информация""'"), Строка(СтрокаКонтактнойИнформации.Объект));
				ВызватьИсключение ТекстОшибки;
			КонецЕсли;
			
			ПараметрыКонтактнойИнформации = Новый Структура;
			ЭтоСсылка = ОбщегоНазначения.ЗначениеСсылочногоТипа(СтрокаКонтактнойИнформации.Объект);
			ПараметрыКонтактнойИнформации.Вставить("ЭтоСсылка", ЭтоСсылка);
			Если Не ЭтоСсылка Тогда
				ВладелецКИ = СтрокаКонтактнойИнформации.Объект; // СправочникОбъект
			КонецЕсли;
			ПараметрыКонтактнойИнформации.Вставить("Периодическая", 
				УправлениеКонтактнойИнформациейСлужебныйПовтИсп.КонтактнаяИнформацияОбъектаСодержитКолонкуДействуетС(
				?(ЭтоСсылка, СтрокаКонтактнойИнформации.Объект, ВладелецКИ.Ссылка)));
			
			ВладельцыКонтактнойИнформации.Вставить(СтрокаКонтактнойИнформации.Объект, ПараметрыКонтактнойИнформации);
		КонецЕсли;
		
		ВосстановитьПустыеЗначениеПредставление(СтрокаКонтактнойИнформации);
		
	КонецЦикла;
	
	Для каждого ВладелецКонтактнойИнформации Из ВладельцыКонтактнойИнформации Цикл
		Отбор = Новый Структура("Объект", ВладелецКонтактнойИнформации.Ключ);
		СтрокиКонтактнойИнформацииОбъекта = КонтактнаяИнформация.НайтиСтроки(Отбор);
		
		Если ВладелецКонтактнойИнформации.Значение["ЭтоСсылка"] Тогда
			УправлениеКонтактнойИнформациейСлужебный.УстановитьКонтактнуюИнформациюОбъектовДляСсылки(ВладелецКонтактнойИнформации, СтрокиКонтактнойИнформацииОбъекта, Замещать);
		Иначе
			УправлениеКонтактнойИнформациейСлужебный.УстановитьКонтактнуюИнформациюОбъектов(ВладелецКонтактнойИнформации, ВладелецКонтактнойИнформации.Ключ, СтрокиКонтактнойИнформацииОбъекта, Замещать);
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

// Добавляет или изменяет контактную информацию у владельца контактной информации.
//
// Параметры:
//  СсылкаИлиОбъект - СправочникСсылка
//                  - ДокументСсылка
//                  - СправочникОбъект
//                  - ДокументОбъект - ссылка или объект владелец
//                                     контактной информации. Для ссылки после добавления контактной информации
//                                     владелец будет записан. Если передан объект, то контактная информация будет
//                                     добавлена без записи. Для сохранения изменений объект необходимо будет
//                                     записать отдельно.
//                  - ДанныеФормыСтруктура:
//                      *  Ссылка - СправочникСсылка - ссылка на объект-владельца контактной информации
//  КонтактнаяИнформация - ТаблицаЗначений - таблица, содержащая контактную информацию
//                                           Описание колонок см. функцию НоваяКонтактнаяИнформация.
//                                           Важно! Если передана пустая таблица значений и указан режим замещения, то
//                                           произойдет очистка всей контактной информации владельца контактной информации.
//  Замещать             - Булево          - если Истина(по умолчанию), то будет заменена
//                                           вся контактная информация по переданном виду контактной информации.
//                                           Если Ложь, то запись будет добавлена. Если вид контактной информации 
//                                           не разрешает ввод нескольких значений, а контактная информация объекта
//                                           уже содержит запись, то запись не будет добавлена.
//
Процедура УстановитьКонтактнуюИнформациюОбъекта(СсылкаИлиОбъект, Знач КонтактнаяИнформация, Замещать = Истина) Экспорт
	
	Если ТипЗнч(СсылкаИлиОбъект) <> Тип("ДанныеФормыСтруктура") Тогда
		ОбъектМетаданных = Метаданные.НайтиПоТипу(ТипЗнч(СсылкаИлиОбъект));
	Иначе
		ОбъектМетаданных = Метаданные.НайтиПоТипу(ТипЗнч(СсылкаИлиОбъект.Ссылка));
	КонецЕсли;
	
	Если Не СодержитКонтактнуюИнформацию(СсылкаИлиОбъект.Ссылка) Тогда
		ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( 
			НСтр("ru = 'Объект %1 не подключен к подсистеме ""Контактная информация""'"), ОбъектМетаданных.Представление());
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;
	
	Если ОбщегоНазначения.ЗначениеСсылочногоТипа(СсылкаИлиОбъект) Тогда
		УправлениеКонтактнойИнформациейСлужебный.УстановитьКонтактнуюИнформациюОбъектаДляСсылки(СсылкаИлиОбъект, КонтактнаяИнформация, ОбъектМетаданных, Замещать);
		Возврат;
	КонецЕсли;
	
	// Очистка контактной информации пустой таблицей.
	Если КонтактнаяИнформация.Количество() = 0 Тогда
		Если Замещать Тогда
			СсылкаИлиОбъект.КонтактнаяИнформация.Очистить();
		КонецЕсли;
		Возврат;
	КонецЕсли;
	
	УправлениеКонтактнойИнформациейСлужебный.УстановитьКонтактнуюИнформациюОбъекта(СсылкаИлиОбъект, КонтактнаяИнформация, ОбъектМетаданных, Замещать);
	
КонецПроцедуры

////////////////////////////////////////////////////////////////////////////////
// Телефонные номера

// Возвращает сведения о телефоне или факсе.
//
// Параметры:
//  КонтактнаяИнформация - Строка - телефон во внутреннем формате JSON или в XML, соответствующем XDTO-пакету контактная
//                                  информация.
//                       - Неопределено - конструктор, возвращает список незаполненных полей телефона.
//
// Возвращаемое значение:
//  Структура:
//    * Представление - Строка - полное представление телефона с добавочным номером и комментарием, например, "+7 495
//                               1234567 (+12) Звонить после 18:00".
//    * КодСтраны     - Строка - код страны. Например, +7.
//    * КодГорода     - Строка - код города. Например, 495.
//    * НомерТелефона - Строка - номер телефона. Например, 1234567.
//    * Добавочный    - Строка - добавочный номер телефона. Например, +12.
//    * Комментарий   - Строка - комментарий к номеру телефона. Например, Звонить после 18:00.
//
Функция СведенияОТелефоне(КонтактнаяИнформация = Неопределено) Экспорт
	
	Результат               = УправлениеКонтактнойИнформациейКлиентСервер.СтруктураПолейТелефона();
	Если КонтактнаяИнформация = Неопределено Тогда
		Возврат Результат;
	КонецЕсли;
	
	ТелефонПоПолям         = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияВСтруктуруJSON(КонтактнаяИнформация, 
		Перечисления.ТипыКонтактнойИнформации.Телефон);
	
	Результат.Представление = Строка(ТелефонПоПолям.Value);
	Результат.КодСтраны     = Строка(ТелефонПоПолям.CountryCode);
	Результат.КодГорода     = Строка(ТелефонПоПолям.AreaCode);
	Результат.НомерТелефона = Строка(ТелефонПоПолям.Number);
	Результат.Добавочный    = Строка(ТелефонПоПолям.ExtNumber);
	Результат.Комментарий   = Строка(ТелефонПоПолям.Comment);
	
	Возврат Результат;
	
КонецФункции

// Возвращает строку с номером телефона без кода и дополнительного номера.
//
// Параметры:
//    КонтактнаяИнформация - Строка - строка JSON или XML контактной информации соответствующая XDTO пакету КонтактнаяИнформация.
//
// Возвращаемое значение:
//    Строка - номер телефона.
//
Функция НомерТелефонаКонтактнойИнформации(Знач КонтактнаяИнформация) Экспорт
	
	Если ПустаяСтрока(КонтактнаяИнформация) Тогда
		Возврат "";
	КонецЕсли;
	
	Если УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВXML(КонтактнаяИнформация) Тогда
		КонтактнаяИнформацияСтруктурой = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияВСтруктуруJSON(КонтактнаяИнформация);
	ИначеЕсли УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВJSON(КонтактнаяИнформация) Тогда
		КонтактнаяИнформацияСтруктурой = УправлениеКонтактнойИнформациейСлужебный.JSONВКонтактнуюИнформациюПоПолям(КонтактнаяИнформация, Перечисления.ТипыКонтактнойИнформации.Телефон);
	КонецЕсли;
	
	Если КонтактнаяИнформацияСтруктурой.Свойство("Number") Тогда
		
		Возврат СокрЛП(КонтактнаяИнформацияСтруктурой.Number);
		
	КонецЕсли;
	
	ВызватьИсключение НСтр("ru = 'Невозможно определить номер, ожидается номер телефона или факса.'");
	
КонецФункции

////////////////////////////////////////////////////////////////////////////////
// Преобразование контактной информации

// Преобразует входящие форматы контактной информации во внутренний формат JSON.
//
// Параметры:
//    КонтактнаяИнформация - Строка - строка в формате XML. Структура XML-документа соответствует XDTO-пакету КонтактнаяИнформация
//                                    или Адрес (для адресов содержащих поля с национальной спецификой).
//                                    Если передана строка во внутреннем формате JSON, то возвращаемое значение будет
//                                    полностью совпадать с ней.
//                         - Структура - см. УправлениеКонтактнойИнформациейКлиентСервер.СтруктураКонтактнойИнформацииПоТипу
//                                       см. РаботаСАдресамиКлиентСервер.ПоляАдреса (для адресов содержащих поля с
//                                       национальной спецификой), см. РаботаСАдресамиКлиентСервер.СтруктураКонтактнойИнформацииПоТипу
//                                       (для других типов контактной информации содержащих поля с национальной спецификой).
//    ОжидаемыйВид - СправочникСсылка.ВидыКонтактнойИнформации
//                 - ПеречислениеСсылка.ТипыКонтактнойИнформации -
//                   используется для определения типа контактной информации, если его невозможно определить из
//                   переданной контактной информации в параметре КонтактнаяИнформация.
//
// Возвращаемое значение:
//     Строка - контактная информация во внутреннем формате JSON.
//              Поля и их описание см. УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеНовойКонтактнойИнформации.
//              Дополнительные поля для конфигурации с поддержкой национальной специфики см. РаботаСАдресамиКлиентСервер.ОписаниеНовойКонтактнойИнформации
//
Функция КонтактнаяИнформацияВJSON(Знач КонтактнаяИнформация, Знач ОжидаемыйВид = Неопределено) Экспорт
	
	Если УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВJSON(КонтактнаяИнформация) Тогда
		Возврат КонтактнаяИнформация;
	КонецЕсли;
	
	НастройкиКонвертации = НастройкиКонвертацииКонтактнойИнформации();
	НастройкиКонвертации.ОбновлятьИдентификаторы = Ложь;
	
	КонтактнаяИнформацияПоПолям = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияВСтруктуруJSON(КонтактнаяИнформация, ОжидаемыйВид, НастройкиКонвертации);
	Возврат УправлениеКонтактнойИнформациейСлужебный.СтруктураВСтрокуJSON(КонтактнаяИнформацияПоПолям);
	
КонецФункции

// Преобразует все входящие форматы контактной информации в XML.
//
// Параметры:
//    ЗначенияПолей - Строка
//                  - Структура
//                  - Соответствие
//                  - СписокЗначений - описание полей контактной информации.
//                    XML должен соответствовать XDTO-пакету КонтактнаяИнформация или Адрес.
//                    Структура, Соответствие, СписокЗначений должен содержать поля в соответствии со структурой
//                    XDTO пакетов КонтактнаяИнформация или Адрес(для конфигурации с поддержкой специфики РФ).
//    Представление - Строка - представление контактной информации. Используется, если невозможно определить
//                    представление из параметра ЗначенияПолей (например, отсутствует поле Представление).
//    ОжидаемыйВид  - СправочникСсылка.ВидыКонтактнойИнформации
//                  - ПеречислениеСсылка.ТипыКонтактнойИнформации -
//                    Используется для определения типа, если его невозможно вычислить по полю ЗначенияПолей.
//
// Возвращаемое значение:
//     Строка - контактная информация в виде XML, соответствующего структуре XDTO пакетов КонтактнаяИнформация и Адрес.
//
Функция КонтактнаяИнформацияВXML(Знач ЗначенияПолей, Знач Представление = "", Знач ОжидаемыйВид = Неопределено) Экспорт
	
	Если УправлениеКонтактнойИнформациейСлужебныйПовтИсп.ДоступенМодульЛокализации() Тогда
		МодульУправлениеКонтактнойИнформациейЛокализация = ОбщегоНазначения.ОбщийМодуль("УправлениеКонтактнойИнформациейЛокализация");
		Результат = МодульУправлениеКонтактнойИнформациейЛокализация.ПривестиКонтактнуюИнформациюXML(Новый Структура(
			"ЗначенияПолей, Представление, ВидКонтактнойИнформации",
		ЗначенияПолей, Представление, ОжидаемыйВид));
		Возврат Результат.ДанныеXML;
	КонецЕсли;
	
	Возврат "";
	
КонецФункции

// Преобразует контактную информацию, хранящуюся в поле ЗначениеПолей, в формат JSON и сохраняет его
// в поле колонки Значение таблицы КонтактнаяИнформация.
// Если колонки ЗначениеПолей и Значение содержат пустые строки, то JSON будет сформирована по представлению.
// В случае, когда параметр СсылкаИлиОбъект содержит объект контактной информации,
// то для сохранения изменений преобразования необходимо будет записать объект отдельно.
// Если передана ссылка, то после конвертирования хотя бы одной строки контактной информации владелец будет записан.
//
// Параметры:
//  СсылкаИлиОбъект - ОпределяемыйТип.ВладелецКонтактнойИнформации - ссылка на объект с контактной информацией.
//                  - СправочникОбъект
//                  - ДокументОбъект - объект-владелец контактной информации (организация,
//                                    контрагент, партнер и т.д.).
// 
// Возвращаемое значение:
//  Булево - если, Истина, то контактная информация была преобразована в JSON.
//
Функция ОбновитьКонтактнуюИнформациюОбъекта(СсылкаИлиОбъект) Экспорт
	
	ОбъектИзменен = Ложь;
	
	ТипОбъекта = ТипЗнч(СсылкаИлиОбъект);
	
	Если Не СодержитКонтактнуюИнформацию(ТипОбъекта) Тогда
		Возврат ОбъектИзменен;
	КонецЕсли;
	
	ОбъектИзменен = УправлениеКонтактнойИнформациейСлужебный.ПреобразоватьКонтактнуюИнформациюВФорматJSON(
		СсылкаИлиОбъект, ТипОбъекта);
	
	Возврат ОбъектИзменен;
	
КонецФункции

// Возвращает объекты, хранящие контактную информацию в устаревших форматах XML или Ключ-Значение,
// и требующие преобразования контактной информации в современный формат JSON.
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - объект с контактной информации у которого требуется определить элемент
//                     содержащие незаполненные поля в JSON.
//  РазмерПорции  - Число - количество объектов, возвращаемых за один вызов. Если не указано, то будут выбраны все объекты.
// 
// Возвращаемое значение:
//  Массив - ссылки на объекты.
//
Функция ОбъектыТребующиеОбновленияКонтактнойИнформации(ОбъектМетаданных, РазмерПорции = Неопределено) Экспорт
	
	Если ОбъектМетаданных.ТабличныеЧасти.Найти("КонтактнаяИнформация") = Неопределено Тогда
		Возврат Новый Массив;
	КонецЕсли;
	
	ПолноеИмяТабличнойЧасти = ОбъектМетаданных.ПолноеИмя() + ".КонтактнаяИнформация";
	
	Запрос = Новый Запрос;
	ТекстЗапроса = "ВЫБРАТЬ РАЗЛИЧНЫЕ
	|	ТабличнаяЧастьКонтактнаяИнформация.Ссылка КАК Ссылка
	|ИЗ
	|	&ТаблицаКонтактнойИнформации КАК ТабличнаяЧастьКонтактнаяИнформация
	|ГДЕ
	|	ВЫРАЗИТЬ(ТабличнаяЧастьКонтактнаяИнформация.Значение КАК СТРОКА(1)) = """" ";
	
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ТаблицаКонтактнойИнформации", ПолноеИмяТабличнойЧасти);
	Если ТипЗнч(РазмерПорции) = Тип("Число") Тогда
		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "ВЫБРАТЬ РАЗЛИЧНЫЕ", "ВЫБРАТЬ РАЗЛИЧНЫЕ ПЕРВЫЕ " + Формат(РазмерПорции,"ЧРГ=' '; ЧГ=0")); // @query-part-1, @query-part-2 
	КонецЕсли;
	
	Запрос.Текст = ТекстЗапроса;
	
	РезультатЗапроса = Запрос.Выполнить();
	
	Если РезультатЗапроса.Пустой() Тогда
		Возврат Новый Массив;
	КонецЕсли;
	
	Результат = РезультатЗапроса.Выгрузить().ВыгрузитьКолонку("Ссылка");
	
	Возврат Результат;
	
КонецФункции

////////////////////////////////////////////////////////////////////////////////
// Работа с контактной информацией из других подсистем.

// Возвращает тип контактной информации.
//
// Параметры:
//    КонтактнаяИнформация - Строка - контактная информация в виде XML, соответствующего структуре XDTO-пакетов
//                                    КонтактнаяИнформация и Адрес.
//
// Возвращаемое значение:
//    ПеречислениеСсылка.ТипыКонтактнойИнформации - соответствующий тип.
//
Функция ТипКонтактнойИнформации(Знач КонтактнаяИнформация) Экспорт
	
	Если УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВJSON(КонтактнаяИнформация) Тогда
		
		КонтактнаяИнформацияСтруктурой = УправлениеКонтактнойИнформациейСлужебный.СтрокуJSONВСтруктуру(КонтактнаяИнформация);
		Если ТипЗнч(КонтактнаяИнформацияСтруктурой) = Тип("Структура") И КонтактнаяИнформацияСтруктурой.Свойство("type") Тогда
			Возврат Перечисления.ТипыКонтактнойИнформации[КонтактнаяИнформацияСтруктурой.type];
		КонецЕсли;
	
	КонецЕсли;
	
	Если УправлениеКонтактнойИнформациейСлужебныйПовтИсп.ДоступенМодульЛокализации() Тогда
	
		МодульУправлениеКонтактнойИнформациейЛокализация = ОбщегоНазначения.ОбщийМодуль("УправлениеКонтактнойИнформациейЛокализация");
		Возврат МодульУправлениеКонтактнойИнформациейЛокализация.ТипКонтактнойИнформации(КонтактнаяИнформация);
		
	КонецЕсли;
		
	Возврат Перечисления.ТипыКонтактнойИнформации.ПустаяСсылка();
	
КонецФункции

// Преобразует представление контактной информации во внутренний формат JSON.
//
// Для адресов, введенных в свободной форме, корректное преобразование не гарантируется.
//
//  Параметры:
//      Представление - Строка  - строковое представление контактной информации, выводимое пользователю.
//      ОжидаемыйВид  - СправочникСсылка.ВидыКонтактнойИнформации
//                    - ПеречислениеСсылка.ТипыКонтактнойИнформации
//                    - Структура - вид или тип контактной информации.
//
// Возвращаемое значение:
//      Строка - контактная информация в виде JSON.
//
Функция КонтактнаяИнформацияПоПредставлению(Представление, ОжидаемыйВид) Экспорт
	
	Возврат УправлениеКонтактнойИнформациейСлужебный.СтруктураВСтрокуJSON(
		УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияПоПредставлению(Представление, ОжидаемыйВид));
	
КонецФункции

// Возвращает представление контактной информации (адреса, телефона, электронной почты и т.п.).
//
// Параметры:
//    КонтактнаяИнформация - Строка - строка JSON или XML контактной информации
//                                    соответствующая XDTO пакетам КонтактнаяИнформация или Адрес.
//                         - ОбъектXDTO - XDTO-объект КонтактнаяИнформация или Адрес.
//                         - Структура - см. РаботаСАдресами.СведенияОбАдресе
//                         - Структура - см. УправлениеКонтактнойИнформацией.СведенияОТелефоне
//    УдалитьВидКонтактнойИнформации - Неопределено - устарел. Оставлен для обратной совместимости.
//
// Возвращаемое значение:
//    Строка - представление контактной информации.
//
Функция ПредставлениеКонтактнойИнформации(Знач КонтактнаяИнформация, Знач УдалитьВидКонтактнойИнформации = Неопределено) Экспорт
	
	Возврат УправлениеКонтактнойИнформациейСлужебный.ПредставлениеКонтактнойИнформации(КонтактнаяИнформация);
	
КонецФункции

// Вычисляет, что адрес был введен в свободной форме.
//
//  Параметры:
//      КонтактнаяИнформация - Строка - строка JSON или XML контактной информации, соответствующая XDTO-пакетам
//                                      КонтактнаяИнформация или Адрес.
//
//  Возвращаемое значение:
//      Булево - новое значение.
//
Функция АдресВведенВСвободнойФорме(Знач КонтактнаяИнформация) Экспорт
	
	Если УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВXML(КонтактнаяИнформация) Тогда
		КонтактнаяИнформацияJSON = КонтактнаяИнформацияВJSON(КонтактнаяИнформация);
		КонтактнаяИнформация = УправлениеКонтактнойИнформациейСлужебный.JSONВКонтактнуюИнформациюПоПолям(КонтактнаяИнформацияJSON, Перечисления.ТипыКонтактнойИнформации.Адрес);
	ИначеЕсли УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВJSON(КонтактнаяИнформация) Тогда
		КонтактнаяИнформация = УправлениеКонтактнойИнформациейСлужебный.JSONВКонтактнуюИнформациюПоПолям(КонтактнаяИнформация, Перечисления.ТипыКонтактнойИнформации.Адрес);
	КонецЕсли;
	
	Возврат УправлениеКонтактнойИнформациейКлиентСервер.ЭтоАдресВСвободнойФорме(КонтактнаяИнформация.AddressType);
	
КонецФункции

// Возвращает комментарий контактной информации.
//
// Параметры:
//  КонтактнаяИнформация - Строка - строка JSON или XML или объект XDTO, соответствующие XDTO-пакетам
//                                   КонтактнаяИнформация или Адрес.
//
// Возвращаемое значение:
//  Строка - комментарий контактной информации или пустая строка,
//           если значение параметра не является контактной информацией.
//
Функция КомментарийКонтактнойИнформации(КонтактнаяИнформация) Экспорт
	
	Если ПустаяСтрока(КонтактнаяИнформация) Тогда
		Возврат "";
	КонецЕсли;

	Если УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВXML(КонтактнаяИнформация) Тогда
		КонтактнаяИнформацияСтруктурой = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияВСтруктуруJSON(КонтактнаяИнформация);
	ИначеЕсли УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВJSON(КонтактнаяИнформация) Тогда
		КонтактнаяИнформацияСтруктурой = УправлениеКонтактнойИнформациейСлужебный.СтрокуJSONВСтруктуру(КонтактнаяИнформация);
	Иначе
		КонтактнаяИнформацияВXML = КонтактнаяИнформацияВXML(КонтактнаяИнформация);
		КонтактнаяИнформацияСтруктурой = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияВСтруктуруJSON(КонтактнаяИнформацияВXML);
	КонецЕсли;
	
	Если КонтактнаяИнформацияСтруктурой.Свойство("Comment") Тогда
		Возврат КонтактнаяИнформацияСтруктурой.Comment;
	КонецЕсли;
	
	Возврат "";
	
КонецФункции

// Устанавливает новый комментарий для контактной информации.
//
// Параметры:
//   КонтактнаяИнформация - Строка
//                        - ОбъектXDTO - строка JSON или XML контактной информации, соответствующая XDTO
//                                       пакетам КонтактнаяИнформация или Адрес.
//   Комментарий          - Строка             - новое значение комментария.
//
Процедура УстановитьКомментарийКонтактнойИнформации(КонтактнаяИнформация, Знач Комментарий) Экспорт
	
	Если УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВJSON(КонтактнаяИнформация) Тогда
		
		КонтактнаяИнформацияСтруктурой = УправлениеКонтактнойИнформациейСлужебный.JSONВКонтактнуюИнформациюПоПолям(КонтактнаяИнформация, Неопределено);
		КонтактнаяИнформацияСтруктурой.comment = Комментарий;
		КонтактнаяИнформация = УправлениеКонтактнойИнформациейСлужебный.СтруктураВСтрокуJSON(КонтактнаяИнформацияСтруктурой);
		Возврат;
	КонецЕсли;
		
	Если УправлениеКонтактнойИнформациейСлужебныйПовтИсп.ДоступенМодульЛокализации() Тогда

		МодульУправлениеКонтактнойИнформациейЛокализация = ОбщегоНазначения.ОбщийМодуль("УправлениеКонтактнойИнформациейЛокализация");
		МодульУправлениеКонтактнойИнформациейЛокализация.УстановитьКомментарийКонтактнойИнформации(КонтактнаяИнформация, Комментарий);
		
	КонецЕсли;
	
КонецПроцедуры

// Возвращает информацию о стране адреса.
// Если переданная строка не содержит информации об адресе, то будет вызвано исключение.
// Если передана пустая строка, то возвращается пустая структура.
// Если страна не существует в справочнике, но есть в классификаторе стран, то поле Ссылка результата не будет заполнено.
// Если страна не существует в классификаторе стран, то будет заполнено только поле Наименование.
//
// Параметры:
//    Адрес - Структура
//          - Строка - адрес в формате JSON или строка XML соответствующая XDTO-пакетам КонтактнаяИнформация
//                     или Адрес.
//
// Возвращаемое значение:
//    Структура - описание страны адреса. Содержит поля:
//        * Ссылка             - СправочникСсылка.СтраныМира
//                             - Неопределено - ссылка на элемент справочника страны мира.
//        * Наименование       - Строка - наименование страны.
//        * Код                - Строка - код страны.
//        * НаименованиеПолное - Строка - полное наименование страны.
//        * КодАльфа2          - Строка - двузначный буквенный код страны Альфа-2.
//        * КодАльфа3          - Строка - трехзначный буквенный код страны Альфа-3.
//
Функция СтранаАдресаКонтактнойИнформации(Знач Адрес) Экспорт
	
	Результат = Новый Структура("Ссылка, Код, Наименование, НаименованиеПолное, КодАльфа2, КодАльфа3");
	
	Если ТипЗнч(Адрес) = Тип("Строка") Тогда
		
		Если ПустаяСтрока(Адрес) Тогда
			Возврат Результат;
		КонецЕсли;
	
		Если УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВXML(Адрес) Тогда
			Адрес = КонтактнаяИнформацияВJSON(Адрес, Перечисления.ТипыКонтактнойИнформации.Адрес);
		КонецЕсли;
		
		Адрес = УправлениеКонтактнойИнформациейСлужебный.JSONВКонтактнуюИнформациюПоПолям(Адрес, Перечисления.ТипыКонтактнойИнформации.Адрес);
		
	ИначеЕсли ТипЗнч(Адрес) <> Тип("Структура") Тогда
		
		ВызватьИсключение НСтр("ru = 'Невозможно определить страну, ожидается адрес.'");
		
	КонецЕсли;
	
	Результат.Наименование = СокрЛП(Адрес.Country);
	ДанныеСтраны = ДанныеСтраныМира(, Результат.Наименование);
	Возврат ?(ДанныеСтраны = Неопределено, Результат, ДанныеСтраны);
	
КонецФункции

// Возвращает домен сетевого адреса для веб-ссылки или адреса электронной почты.
//
// Параметры:
//    КонтактнаяИнформация - Строка - строка JSON или XML контактной информации соответствующая XDTO пакету КонтактнаяИнформация.
//
// Возвращаемое значение:
//    Строка - домен адреса.
//
Функция ДоменАдресаКонтактнойИнформации(Знач КонтактнаяИнформация) Экспорт
	
	Если ПустаяСтрока(КонтактнаяИнформация) Тогда
		Возврат "";
	КонецЕсли;
	
	Если УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВXML(КонтактнаяИнформация) Тогда
		КонтактнаяИнформацияСтруктурой = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияВСтруктуруJSON(КонтактнаяИнформация);
	ИначеЕсли УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВJSON(КонтактнаяИнформация) Тогда
		КонтактнаяИнформацияСтруктурой = УправлениеКонтактнойИнформациейСлужебный.СтрокуJSONВСтруктуру(КонтактнаяИнформация);
	КонецЕсли;
	
	Если КонтактнаяИнформацияСтруктурой.Свойство("Type") И КонтактнаяИнформацияСтруктурой.Свойство("Value") Тогда
		
		ДоменАдреса = СокрЛП(КонтактнаяИнформацияСтруктурой.Value);
		Если ТипКонтактнойИнформацииПоНаименованию(КонтактнаяИнформацияСтруктурой.Type) = Перечисления.ТипыКонтактнойИнформации.ВебСтраница Тогда
			
			Позиция = СтрНайти(ДоменАдреса, "://");
			Если Позиция > 0 Тогда
				ДоменАдреса = Сред(ДоменАдреса, Позиция + 3);
			КонецЕсли;
			Позиция = СтрНайти(ДоменАдреса, "/");
			Возврат ?(Позиция = 0, ДоменАдреса, Лев(ДоменАдреса, Позиция - 1));
			
		ИначеЕсли ТипКонтактнойИнформацииПоНаименованию(КонтактнаяИнформацияСтруктурой.Type) = Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты Тогда
			
			Позиция = СтрНайти(ДоменАдреса, "@");
			Возврат ?(Позиция = 0, ДоменАдреса, Сред(ДоменАдреса, Позиция + 1));
			
		КонецЕсли;
		
	КонецЕсли;
	
	ВызватьИсключение НСтр("ru = 'Невозможно определить домен, ожидается электронная почта или веб-ссылка.'");
КонецФункции

// Сравнивает два экземпляра контактной информации.
//
// Параметры:
//    Данные1 - ОбъектXDTO - объект с контактной информацией.
//            - Строка     - контактная информация в формате XML.
//            - Структура  - описание контактной информацию. Ожидаются поля:
//                 * ЗначенияПолей - Строка
//                                 - Структура
//                                 - СписокЗначений
//                                 - Соответствие - поля контактной информации.
//                 * Представление - Строка - представление. Используется в случае, если не удалось вычислить
//                                            представление из ЗначенияПолей (отсутствие в них поля Представление).
//                 * Комментарий - Строка - комментарий. Используется в том случае, если не удалось вычислить комментарий
//                                          из ЗначенияПолей.
//                 * ВидКонтактнойИнформации - СправочникСсылка.ВидыКонтактнойИнформации
//                                           - ПеречислениеСсылка.ТипыКонтактнойИнформации
//                                           - Структура -
//                                             используется в том случае, если не удалось вычислить тип из ЗначенияПолей.
//    Данные2 - ОбъектXDTO
//            - Строка
//            - Структура - смотри описание параметра Данные1.
//
// Возвращаемое значение:
//     ТаблицаЗначений: - таблица отличающихся полей со следующими колонками:
//        * Путь      - Строка - XPath, идентифицирующий отличающееся значение. Значение "ТипКонтактнойИнформации"
//                               означает, что переданные экземпляры контактной информации различаются типом.
//        * Описание  - Строка - описание отличающегося реквизита в терминах предметной области.
//        * Значение1 - Строка - значение, соответствующая объекту, переданному в параметре Данные1.
//        * Значение2 - Строка - значение, соответствующая объекту, переданному в параметре Данные2.
//
Функция РазличияКонтактнойИнформации(Знач Данные1, Знач Данные2) Экспорт
	
	Результат = Новый ТаблицаЗначений;
	Результат.Колонки.Добавить("Путь", ОбщегоНазначения.ОписаниеТипаСтрока(0));
	Результат.Колонки.Добавить("Описание", ОбщегоНазначения.ОписаниеТипаСтрока(0));
	Результат.Колонки.Добавить("Значение1", ОбщегоНазначения.ОписаниеТипаСтрока(0));
	Результат.Колонки.Добавить("Значение2", ОбщегоНазначения.ОписаниеТипаСтрока(0));
	
	Если Не УправлениеКонтактнойИнформациейСлужебныйПовтИсп.ДоступенМодульЛокализации() Тогда
		Возврат Результат;
	КонецЕсли;
	
	МодульУправлениеКонтактнойИнформациейЛокализация = ОбщегоНазначения.ОбщийМодуль("УправлениеКонтактнойИнформациейЛокализация");
	Возврат МодульУправлениеКонтактнойИнформациейЛокализация.РазличияКонтактнойИнформации(Данные1, Данные2, Результат);
	
КонецФункции

// Создает временную таблицу с контактной информацией нескольких объектов.
//
// Параметры:
//    МенеджерВременныхТаблиц  - МенеджерВременныхТаблиц - в менеджере создается временная таблица
//     ВТКонтактнаяИнформация с полями:
//     * Объект        - ЛюбаяСсылка - владелец контактной информации.
//     * Вид           - СправочникСсылка.ВидыКонтактнойИнформации - ссылка на вид контактной информации.
//     * Тип           - ПеречислениеСсылка.ТипыКонтактнойИнформации - тип контактной информации.
//     * ЗначенияПолей - Строка - XML соответствующий XDTO пакету КонтактнаяИнформация или Адрес.
//     * Представление - Строка - представление контактной информации.
//    МассивОбъектов           - Массив - владельцы контактной информации.
//    ТипыКонтактнойИнформации - Массив - если указаны, то временная таблица будет содержать только контактную
//                                        информацию этих типов.
//    ВидыКонтактнойИнформации - Массив - если указаны, то временная таблица будет содержать только контактную
//                                        информацию этих видов.
//    Дата                     - Дата   - дата, с которой действует запись контактной информации, используется при
//                                        хранении истории изменения контактной информации. Если владелец хранит историю
//                                        изменений, то при несоответствии параметра дате будет вызвано исключение.
//
Процедура СоздатьВТКонтактнаяИнформация(МенеджерВременныхТаблиц, МассивОбъектов, ТипыКонтактнойИнформации = Неопределено, ВидыКонтактнойИнформации = Неопределено, Дата = Неопределено) Экспорт
	
	Если ТипЗнч(МассивОбъектов) <> Тип("Массив") ИЛИ МассивОбъектов.Количество() = 0 Тогда
		ВызватьИсключение НСтр("ru = 'Неверное значение для массива владельцев контактной информации.'");
	КонецЕсли;
	
	ОбъектыСГруппировкойПоТипам = Новый Соответствие;
	Для каждого Ссылка Из МассивОбъектов Цикл
		ТипОбъекта = ТипЗнч(Ссылка);
		НайденныйОбъект = ОбъектыСГруппировкойПоТипам.Получить(ТипОбъекта); // Массив
		Если НайденныйОбъект = Неопределено Тогда
			НаборСсылок = Новый Массив;
			НаборСсылок.Добавить(Ссылка);
			ОбъектыСГруппировкойПоТипам.Вставить(ТипОбъекта, НаборСсылок);
		Иначе
			НайденныйОбъект.Добавить(Ссылка);
		КонецЕсли;
	КонецЦикла;
	
	Запрос = Новый Запрос();
	ТекстЗапросаПодготовкаДанных = "";
	
	Для каждого ОбъектСКонтактнойИнформацией Из ОбъектыСГруппировкойПоТипам Цикл
		
		Если Не СодержитКонтактнуюИнформацию(ОбъектСКонтактнойИнформацией.Ключ) Тогда
			ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = '%1 не содержит контактную информацию.'"), Строка(ОбъектСКонтактнойИнформацией.Ключ));
		КонецЕсли;
		
		МетаданныеОбъекта = Метаданные.НайтиПоТипу(ОбъектСКонтактнойИнформацией.Ключ);
		ИмяТаблицы = МетаданныеОбъекта.Имя;
		
		Если МетаданныеОбъекта.ТабличныеЧасти.КонтактнаяИнформация.Реквизиты.Найти("ДействуетС") <> Неопределено Тогда
			
			ТекстЗапросаПодготовкаДанных = ТекстЗапросаПодготовкаДанных + "ВЫБРАТЬ РАЗРЕШЕННЫЕ
			|	КонтактнаяИнформация.Ссылка КАК Объект,
			|	КонтактнаяИнформация.Вид КАК Вид,
			|	МИНИМУМ(КонтактнаяИнформация.НомерСтроки) КАК НомерСтроки,
			|	МАКСИМУМ(КонтактнаяИнформация.ДействуетС) КАК ДействуетС
			|ПОМЕСТИТЬ СрезКонтактнойИнформации" + ИмяТаблицы + "
			|ИЗ
			|	" + МетаданныеОбъекта.ПолноеИмя() + ".КонтактнаяИнформация КАК КонтактнаяИнформация
			|ГДЕ
			|	КонтактнаяИнформация.Ссылка В (&МассивОбъектов" + ИмяТаблицы + ")
			|	И КонтактнаяИнформация.ДействуетС <= &ДействуетС
			|	И КонтактнаяИнформация.Вид <> ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ПустаяСсылка)
			|	И КонтактнаяИнформация.Тип <> ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.ПустаяСсылка)
			|
			|СГРУППИРОВАТЬ ПО
			|	КонтактнаяИнформация.Вид, КонтактнаяИнформация.Ссылка
			|;" // @Query-part-1
			
		КонецЕсли;
	КонецЦикла;
	
	ТекстЗапроса = "";
	ЭтоПервыйЗапрос = Истина;
	Для каждого ОбъектСКонтактнойИнформацией Из ОбъектыСГруппировкойПоТипам Цикл
		ТекстЗапроса = ТекстЗапроса + ?(НЕ ПустаяСтрока(ТекстЗапроса), Символы.ПС + " ОБЪЕДИНИТЬ ВСЕ " + Символы.ПС, "");
		МетаданныеОбъекта = Метаданные.НайтиПоТипу(ОбъектСКонтактнойИнформацией.Ключ);
		ИмяТаблицы = МетаданныеОбъекта.Имя;
		
		ЕстьИдентификаторСтрокиТабличнойЧасти = МетаданныеОбъекта.ТабличныеЧасти.КонтактнаяИнформация.Реквизиты.Найти("ИдентификаторСтрокиТабличнойЧасти") <> Неопределено;
		
		Если МетаданныеОбъекта.ТабличныеЧасти.КонтактнаяИнформация.Реквизиты.Найти("ДействуетС") <> Неопределено Тогда
			Если ТипЗнч(Дата) <> Тип("Дата") Тогда
				ВызватьИсключение НСтр("ru = 'Для получения контактной информации, хранящей историю изменений,
					|требуется указывать дату, с которой действует запись контактной информации.'");
			КонецЕсли;
			
			УсловияОтбора = ?(ВидыКонтактнойИнформации = Неопределено, "", " КонтактнаяИнформация.Вид В (&ВидыКонтактнойИнформации)"); // @query-part-2
			Если ПустаяСтрока(УсловияОтбора) Тогда
				УсловиеИ = "";
			Иначе
				УсловиеИ = " И ";
			КонецЕсли;
			УсловияОтбора = УсловияОтбора + ?(ТипыКонтактнойИнформации = Неопределено, "", УсловиеИ + " КонтактнаяИнформация.Тип В (&ТипыКонтактнойИнформации)"); // @query-part-2
			Если НЕ ПустаяСтрока(УсловияОтбора) Тогда
				УсловияОтбора = " ГДЕ " + УсловияОтбора;
			КонецЕсли;
			
			ТекстЗапроса = ТекстЗапроса + "ВЫБРАТЬ
			|	КонтактнаяИнформация.Ссылка КАК Объект,
			|	КонтактнаяИнформация.Вид КАК Вид,
			|	КонтактнаяИнформация.Тип КАК Тип,
			|	КонтактнаяИнформация.НомерСтроки КАК НомерСтроки,
			|	КонтактнаяИнформация.ДействуетС КАК ДействуетС,
			|	КонтактнаяИнформация.Представление КАК Представление,
			|	КонтактнаяИнформация.Значение,
			|	КонтактнаяИнформация.ЗначенияПолей,
			|	0 КАК ИдентификаторСтрокиТабличнойЧасти
			|ИЗ
			|	&СрезКонтактнойИнформации КАК СрезКонтактнойИнформации
			|		ЛЕВОЕ СОЕДИНЕНИЕ #КонтактнаяИнформация КАК КонтактнаяИнформация
			|		ПО СрезКонтактнойИнформации.Вид = КонтактнаяИнформация.Вид
			|			И СрезКонтактнойИнформации.ДействуетС = КонтактнаяИнформация.ДействуетС
			|			И СрезКонтактнойИнформации.Объект = КонтактнаяИнформация.Ссылка " + УсловияОтбора;
			
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&СрезКонтактнойИнформации", "СрезКонтактнойИнформации" + ИмяТаблицы);
			
		Иначе
			ТекстЗапроса = ТекстЗапроса + "ВЫБРАТЬ
			|	КонтактнаяИнформация.Ссылка КАК Объект,
			|	КонтактнаяИнформация.Вид КАК Вид,
			|	КонтактнаяИнформация.Тип КАК Тип,
			|	КонтактнаяИнформация.НомерСтроки КАК НомерСтроки,
			|	ДАТАВРЕМЯ(1,1,1) КАК ДействуетС,
			|	КонтактнаяИнформация.Представление КАК Представление,
			|	КонтактнаяИнформация.Значение,
			|	КонтактнаяИнформация.ЗначенияПолей КАК ЗначенияПолей,
			|	0 КАК ИдентификаторСтрокиТабличнойЧасти
			|ИЗ
			|	#КонтактнаяИнформация КАК КонтактнаяИнформация
			|ГДЕ
			| КонтактнаяИнформация.Вид <> ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ПустаяСсылка)
			| И КонтактнаяИнформация.Тип <> ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.ПустаяСсылка)
			| И КонтактнаяИнформация.Ссылка В (&МассивОбъектовИмяТаблицы)
			| И &УсловиеГдеТипКонтактнойИнформации
			| И &УсловиеГдеВидКонтактнойИнформации
			|";
			
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеГдеТипКонтактнойИнформации",
				?(ТипыКонтактнойИнформации = Неопределено, "ИСТИНА", "КонтактнаяИнформация.Тип В (&ТипыКонтактнойИнформации)")); // @query-part-2
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеГдеВидКонтактнойИнформации",
				?(ВидыКонтактнойИнформации = Неопределено, "ИСТИНА", "КонтактнаяИнформация.Вид В (&ВидыКонтактнойИнформации)")); // @query-part-2
			
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&МассивОбъектовИмяТаблицы", "&МассивОбъектов" + ИмяТаблицы);
			
		КонецЕсли;
		
		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#КонтактнаяИнформация" , МетаданныеОбъекта.ПолноеИмя() + ".КонтактнаяИнформация"); // @Query-part-1, @Query-part-2
		
		Если ЭтоПервыйЗапрос Тогда
			
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "ВЫБРАТЬ" , "ВЫБРАТЬ РАЗРЕШЕННЫЕ"); // @Query-part-1, @Query-part-2
			
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, 
			"ИЗ" , "ПОМЕСТИТЬ ВТКонтактнаяИнформация "+ Символы.ПС + "ИЗ"); // @Query-part-1, @Query-part-2, @Query-part-3
			
			ЭтоПервыйЗапрос = Ложь;
			
		КонецЕсли;
		
		Если ЕстьИдентификаторСтрокиТабличнойЧасти Тогда
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "0 КАК ИдентификаторСтрокиТабличнойЧасти",
				"КонтактнаяИнформация.ИдентификаторСтрокиТабличнойЧасти КАК ИдентификаторСтрокиТабличнойЧасти"); // @Query-part-1, @Query-part-2
		КонецЕсли;
		
		Запрос.УстановитьПараметр("МассивОбъектов" + ИмяТаблицы, ОбъектСКонтактнойИнформацией.Значение);
	КонецЦикла;
	
	Запрос.Текст = ТекстЗапросаПодготовкаДанных + ТекстЗапроса;
	Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
	
	Запрос.УстановитьПараметр("ДействуетС", Дата);
	Запрос.УстановитьПараметр("ТипыКонтактнойИнформации", ТипыКонтактнойИнформации);
	Запрос.УстановитьПараметр("ВидыКонтактнойИнформации", ВидыКонтактнойИнформации);
	Запрос.Выполнить();
	
КонецПроцедуры

////////////////////////////////////////////////////////////////////////////////
// Страны мира

// Возвращает данные о стране по справочнику стран мира или классификатору.
//
// Параметры:
//    КодСтраны    - Строка
//                 - Число - код страны по классификатору. Если не указано, то поиск по коду не производится.
//    Наименование - Строка - наименование страны, в т.ч. и международное. Если не указано, то поиск по наименованию не производится.
//
// Возвращаемое значение:
//    Структура - описание страны. Содержит поля:
//        * Ссылка             - СправочникСсылка.СтраныМира
//                             - Неопределено - соответствующий элемент справочника Страны мира.
//        * Наименование       - Строка - наименование страны.
//        * Код                - Строка - код страны.
//        * НаименованиеПолное - Строка - полное наименование страны.
//        * КодАльфа2          - Строка - двузначный буквенный код страны альфа-2.
//        * КодАльфа3          - Строка - трехзначный буквенный код страны альфа-3.
//        * УчастникЕАЭС       - Булево - страна-участник ЕАЭС.
//        * МеждународноеНаименование - Строка - международное наименование страны мира
//    Неопределено - страна не существует.
//
Функция ДанныеСтраныМира(Знач КодСтраны = Неопределено, Знач Наименование = Неопределено) Экспорт
	Результат = Неопределено;
	
	Если КодСтраны = Неопределено И Наименование = Неопределено Тогда
		Возврат Результат;
	КонецЕсли;
	
	УсловиеПоиска = Новый Массив;
	ФильтрКлассификатора = Новый Структура;
	
	НормализованныйКод = КодСтраныМира(КодСтраны);
	Если КодСтраны <> Неопределено Тогда
		УсловиеПоиска.Добавить("Код=" + КонтрольКавычекВСтроке(НормализованныйКод));
		ФильтрКлассификатора.Вставить("Код", НормализованныйКод);
	КонецЕсли;
	
	Если Наименование <> Неопределено Тогда
		ШаблонНаименование = " (Наименование = %1 ИЛИ МеждународноеНаименование = %1)";
		УсловиеПоиска.Добавить(СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонНаименование,
			КонтрольКавычекВСтроке(Наименование)));
		
		ФильтрКлассификатора.Вставить("Наименование", Наименование);
	КонецЕсли;
	УсловиеПоиска = СтрСоединить(УсловиеПоиска, " И ");
	
	Результат = Новый Структура;
	Результат.Вставить("Ссылка");
	Результат.Вставить("Код",                       "");
	Результат.Вставить("Наименование",              "");
	Результат.Вставить("НаименованиеПолное",        "");
	Результат.Вставить("МеждународноеНаименование", "");
	Результат.Вставить("КодАльфа2",                 "");
	Результат.Вставить("КодАльфа3",                 "");
	Результат.Вставить("УчастникЕАЭС",              Ложь);
	
	ТекстЗапроса = "ВЫБРАТЬ ПЕРВЫЕ 1
	|	Ссылка, Код, Наименование, НаименованиеПолное,
	|	МеждународноеНаименование, КодАльфа2, КодАльфа3, УчастникЕАЭС
	|ИЗ
	|	Справочник.СтраныМира
	|ГДЕ
	|	&УсловиеПоиска
	|УПОРЯДОЧИТЬ ПО
	|	Наименование";
	
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеПоиска", УсловиеПоиска);
	Запрос = Новый Запрос(ТекстЗапроса);
	
	Выборка = Запрос.Выполнить().Выбрать();
	
	Если Выборка.Следующий() Тогда 
		ЗаполнитьЗначенияСвойств(Результат, Выборка);
	Иначе
		
		Если Не УправлениеКонтактнойИнформациейСлужебныйПовтИсп.ДоступныМодулиРаботаСАдресами() Тогда
			Возврат Неопределено;
		КонецЕсли;
		
		МодульРаботаСАдресами = ОбщегоНазначения.ОбщийМодуль("РаботаСАдресами");
		ДанныеКлассификатора = МодульРаботаСАдресами.ТаблицаКлассификатора();
		СтрокиДанных = ДанныеКлассификатора.НайтиСтроки(ФильтрКлассификатора);
		Если СтрокиДанных.Количество() = 0 Тогда
			Возврат Неопределено;
		Иначе
			ЗаполнитьЗначенияСвойств(Результат, СтрокиДанных[0]);
		КонецЕсли;
		
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Возвращает данные страны по коду.
//
// Параметры:
//  Код     - Строка
//          - Число - код страны по классификатору.
//  ТипКода - Строка - варианты: КодСтраны (по умолчанию), Альфа2, Альфа3.
// 
// Возвращаемое значение:
//  Структура - описание страны. Содержит поля:
//     * Наименование       - Строка - наименование страны.
//     * Код                - Строка - код страны.
//     * НаименованиеПолное - Строка - полное наименование страны.
//     * КодАльфа2          - Строка - двузначный буквенный код страны альфа-2.
//     * КодАльфа3          - Строка - трехзначный буквенный код страны альфа-3.
//     * УчастникЕАЭС       - Булево - страна-участник ЕАЭС.
//  Неопределено - страна не существует.
//
Функция ДанныеКлассификатораСтранМираПоКоду(Знач Код, Знач ТипКода = "КодСтраны") Экспорт
	
	Если Не УправлениеКонтактнойИнформациейСлужебныйПовтИсп.ДоступныМодулиРаботаСАдресами()  Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Результат = Новый Структура;
	Результат.Вставить("Код",                       "");
	Результат.Вставить("Наименование",              "");
	Результат.Вставить("НаименованиеПолное",        "");
	Результат.Вставить("КодАльфа2",                 "");
	Результат.Вставить("КодАльфа3",                 "");
	Результат.Вставить("УчастникЕАЭС",              Ложь);
	
	МодульРаботаСАдресами = ОбщегоНазначения.ОбщийМодуль("РаботаСАдресами");
	ДанныеКлассификатора = МодульРаботаСАдресами.ТаблицаКлассификатора();
	
	Если СтрСравнить(ТипКода, "Альфа2") = 0 Тогда
		СтрокаДанных = ДанныеКлассификатора.Найти(ВРег(Код), "КодАльфа2");
	ИначеЕсли СтрСравнить(ТипКода, "Альфа3") = 0 Тогда
		СтрокаДанных = ДанныеКлассификатора.Найти(ВРег(Код), "КодАльфа3");
	Иначе
		СтрокаДанных = ДанныеКлассификатора.Найти(КодСтраныМира(Код), "Код");
	КонецЕсли;
	
	Если СтрокаДанных = Неопределено Тогда
		Возврат Неопределено
	КонецЕсли;
	
	ЗаполнитьЗначенияСвойств(Результат, СтрокаДанных);
	
	Возврат Результат;
	
КонецФункции

// Возвращает данные о стране по наименованию страны.
//
// Параметры:
//    Наименование - Строка - наименование страны.
//
// Возвращаемое значение:
//    Структура - описание страны. Содержит поля:
//       * Наименование       - Строка - наименование страны.
//       * Код                - Строка - код страны.
//       * НаименованиеПолное - Строка - полное наименование страны.
//       * КодАльфа2          - Строка - двузначный буквенный код страны альфа-2.
//       * КодАльфа3          - Строка - трехзначный буквенный код страны альфа-3.
//       * УчастникЕАЭС       - Булево - страна-участник ЕАЭС.
//    Неопределено - страна не существует в классификаторе.
//
Функция ДанныеКлассификатораСтранМираПоНаименованию(Знач Наименование) Экспорт
	
	Если Не УправлениеКонтактнойИнформациейСлужебныйПовтИсп.ДоступныМодулиРаботаСАдресами() Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Результат = Новый Структура;
	Результат.Вставить("Код",                       "");
	Результат.Вставить("Наименование",              "");
	Результат.Вставить("НаименованиеПолное",        "");
	Результат.Вставить("КодАльфа2",                 "");
	Результат.Вставить("КодАльфа3",                 "");
	Результат.Вставить("УчастникЕАЭС",              Ложь);
	
	МодульРаботаСАдресами = ОбщегоНазначения.ОбщийМодуль("РаботаСАдресами");
	ДанныеКлассификатора = МодульРаботаСАдресами.ТаблицаКлассификатора();
	
	СтрокаДанных = ДанныеКлассификатора.Найти(Наименование, "Наименование");
	Если СтрокаДанных = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	ЗаполнитьЗначенияСвойств(Результат, СтрокаДанных);
	
	Возврат Результат;
	
КонецФункции

// Возвращает ссылку на элемент справочника страны мира по коду или наименованию.
// Если элемент справочника СтраныМиры не существует, то он будет создан на основании данных заполнения.
//
// Параметры:
//  КодИлиНаименование - Строка    - код страны, код Альфа2, код Альфа3 или наименование страны, в т.ч. международное.
//  ДанныеЗаполнения   - Структура - данные для заполнения в случае создания нового элемента.
//                                   Ключи структуры соответствуют реквизитам справочника СтраныМира.
// 
// Возвращаемое значение:
//  СправочникСсылка.СтраныМира - если найдено несколько значений, то будет возвращено первое.
//                                Если не существует и данные заполнения не указаны, то возвращается пустая ссылка.
//
Функция СтранаМираПоКодуИлиНаименованию(КодИлиНаименование, ДанныеЗаполнения = Неопределено) Экспорт
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
	"ВЫБРАТЬ
	|	СтраныМира.Ссылка КАК Ссылка
	|ИЗ
	|	Справочник.СтраныМира КАК СтраныМира
	|ГДЕ
	|	(СтраныМира.Код = &КодИлиНаименование
	|			ИЛИ СтраныМира.КодАльфа2 = &КодИлиНаименование
	|			ИЛИ СтраныМира.КодАльфа3 = &КодИлиНаименование
	|			ИЛИ СтраныМира.Наименование = &КодИлиНаименование
	|			ИЛИ СтраныМира.МеждународноеНаименование = &КодИлиНаименование
	|			ИЛИ СтраныМира.НаименованиеПолное = &КодИлиНаименование)";
	
	Запрос.УстановитьПараметр("КодИлиНаименование", КодИлиНаименование);
	РезультатЗапроса = Запрос.Выполнить().Выбрать();
	
	Если РезультатЗапроса.Следующий() Тогда
		Возврат РезультатЗапроса.Ссылка;
	КонецЕсли;
	
	Если Не УправлениеКонтактнойИнформациейСлужебныйПовтИсп.ДоступныМодулиРаботаСАдресами()  Тогда
		Возврат Справочники.СтраныМира.ПустаяСсылка();
	КонецЕсли;
	
	МодульРаботаСАдресами = ОбщегоНазначения.ОбщийМодуль("РаботаСАдресами");
	ДанныеКлассификатора = МодульРаботаСАдресами.ТаблицаКлассификатора();
	
	Запрос = Новый Запрос;
	Запрос.Текст = "ВЫБРАТЬ
	|	ТаблицаКлассификатор.Код,
	|	ТаблицаКлассификатор.КодАльфа2,
	|	ТаблицаКлассификатор.КодАльфа3,
	|	ТаблицаКлассификатор.Наименование,
	|	ТаблицаКлассификатор.НаименованиеПолное,
	|	ТаблицаКлассификатор.МеждународноеНаименование,
	|	ТаблицаКлассификатор.УчастникЕАЭС,
	|	ТаблицаКлассификатор.Неактуальный
	|ПОМЕСТИТЬ ТаблицаКлассификатор
	|ИЗ
	|	&ТаблицаКлассификатор КАК ТаблицаКлассификатор
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	СтранаМира.Код,
	|	СтранаМира.КодАльфа2,
	|	СтранаМира.КодАльфа3,
	|	СтранаМира.Наименование,
	|	СтранаМира.НаименованиеПолное,
	|	СтранаМира.МеждународноеНаименование,
	|	СтранаМира.УчастникЕАЭС,
	|	СтранаМира.Неактуальный
	|ИЗ
	|	ТаблицаКлассификатор КАК СтранаМира
	|ГДЕ
	|	(СтранаМира.Код = &КодИлиНаименование
	|			ИЛИ СтранаМира.КодАльфа2 = &КодИлиНаименование
	|			ИЛИ СтранаМира.КодАльфа3 = &КодИлиНаименование
	|			ИЛИ СтранаМира.Наименование = &КодИлиНаименование
	|			ИЛИ СтранаМира.МеждународноеНаименование = &КодИлиНаименование
	|			ИЛИ СтранаМира.НаименованиеПолное = &КодИлиНаименование)";
	
	Запрос.УстановитьПараметр("ТаблицаКлассификатор", ДанныеКлассификатора);
	Запрос.УстановитьПараметр("КодИлиНаименование",   КодИлиНаименование);
	РезультатЗапроса = Запрос.Выполнить().Выбрать();
	
	Если РезультатЗапроса.Следующий() Тогда
		ДанныеЗаполнения = ОписаниеСтраныМира(ОбщегоНазначения.СтрокаТаблицыЗначенийВСтруктуру(РезультатЗапроса));
	КонецЕсли;
	
	Если ДанныеЗаполнения = Неопределено
		ИЛИ НЕ ДанныеЗаполнения.Свойство("Наименование")
		ИЛИ ПустаяСтрока(ДанныеЗаполнения.Наименование) Тогда
		Возврат Справочники.СтраныМира.ПустаяСсылка();
	КонецЕсли;
	
	УстановитьПривилегированныйРежим(Истина);
	ОбъектСтраны = Справочники.СтраныМира.СоздатьЭлемент();
	ЗаполнитьЗначенияСвойств(ОбъектСтраны, ДанныеЗаполнения);
	ОбъектСтраны.Записать();
	
	Возврат ОбъектСтраны.Ссылка;
	
КонецФункции

// Возвращает список стран Евразийского экономического союза (ЕАЭС).
// Вызов функции может инициировать http-запрос к веб-сервису по работе с классификаторами
// для получения актуального списка всех стран участников ЕАЭС.
//
// Возвращаемое значение:
//  - ТаблицаЗначений - список стран Евразийского экономического союза (ЕАЭС):
//     * Ссылка             - СправочникСсылка.СтраныМира - ссылка на элемент справочника страны.
//     * Наименование       - Строка - наименование страны.
//     * Код                - Строка - код страны.
//     * НаименованиеПолное - Строка - полное наименование страны.
//     * КодАльфа2          - Строка - двузначный буквенный код страны альфа-2.
//     * КодАльфа3          - Строка - трехзначный буквенный код страны альфа-3.
//     * МеждународноеНаименование - Строка - международное наименование страны мира
//
Функция СтраныУчастникиЕАЭС() Экспорт
	
	СтраныЕАЭС = ПользовательскиеСтраныЕАЭС();
	
	Если Не УправлениеКонтактнойИнформациейСлужебныйПовтИсп.ДоступныМодулиРаботаСАдресами() Тогда
		Возврат СтраныЕАЭС;
	КонецЕсли;
	
	МодульРаботаСАдресами = ОбщегоНазначения.ОбщийМодуль("РаботаСАдресами");
	ДанныеКлассификатора = МодульРаботаСАдресами.ТаблицаКлассификатора();
	
	Для каждого Страна Из ДанныеКлассификатора Цикл
		Если Страна.УчастникЕАЭС Тогда
			Отбор = Новый Структура();
			Отбор.Вставить("Наименование", Страна.Наименование);
			Отбор.Вставить("Код", Страна.Код);
			Отбор.Вставить("НаименованиеПолное", Страна.НаименованиеПолное);
			Отбор.Вставить("КодАльфа2", Страна.КодАльфа2);
			Отбор.Вставить("КодАльфа3", Страна.КодАльфа3);
			НайденныеСтроки = СтраныЕАЭС.НайтиСтроки(Отбор);
			Если НайденныеСтроки.Количество() = 0 Тогда
				НоваяСтрока = СтраныЕАЭС.Добавить();
				ЗаполнитьЗначенияСвойств(НоваяСтрока, Отбор);
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
	
	Возврат СтраныЕАЭС;

КонецФункции

// Определяет, является ли страна участником Евразийского экономического союза (ЕАЭС).
//
// Параметры:
//  Страна - Строка
//         - СправочникСсылка.СтраныМира - код страны, код Альфа2, код Альфа3,
//                  наименование страны или ссылка на элемент справочника Страны мира.
// Возвращаемое значение:
//    Булево - если Истина, то страна является государством-участником ЕАЭС.
//
Функция ЭтоСтранаУчастникЕАЭС(Страна) Экспорт
	
	Если ТипЗнч(Страна) = ТипЗнч(Справочники.СтраныМира.ПустаяСсылка()) Тогда
		Запрос = Новый Запрос;
		Запрос.Текст = 
			"ВЫБРАТЬ
			|	СтраныМира.УчастникЕАЭС КАК УчастникЕАЭС
			|ИЗ
			|	Справочник.СтраныМира КАК СтраныМира
			|ГДЕ
			|	СтраныМира.Ссылка = &Ссылка";
		
		Запрос.УстановитьПараметр("Ссылка", Страна);
		
		РезультатЗапроса = Запрос.Выполнить();
		
		Если НЕ РезультатЗапроса.Пустой() Тогда
			СтрокаРезультата = РезультатЗапроса.Выбрать();
			Если СтрокаРезультата.Следующий() Тогда
				Возврат (СтрокаРезультата.УчастникЕАЭС = ИСТИНА);
			КонецЕсли;
		КонецЕсли;
		
	Иначе
		НайденнаяСтрана =  СтранаМираПоКодуИлиНаименованию(Страна);
		Если ЗначениеЗаполнено(НайденнаяСтрана) Тогда
			Возврат ОбщегоНазначения.ЗначениеРеквизитаОбъекта(НайденнаяСтрана, "УчастникЕАЭС");
		КонецЕсли;
		
	КонецЕсли;
	
	Возврат Ложь;
	
КонецФункции

////////////////////////////////////////////////////////////////////////////////
// Обработчики событий формы и модуля объекта вызываемые при внедрении подсистемы.

// Обработчик для события формы ПриСозданииНаСервере.
// Вызывается из модуля формы объекта-владельца КИ при внедрении подсистемы.
//
// Параметры:
//    Форма - ФормаКлиентскогоПриложения - форма объекта-владельца, предназначенная для вывода контактной информации.
//    Объект - СправочникСсылка
//           - ДокументСсылка
//           - СправочникОбъект
//           - ДокументОбъект - объект-владелец контактной информации. 
//                              Если это ссылка, то контактная информация
//                              будет получена из объекта по ссылке, иначе из таблицы КонтактнаяИнформация объекта.
//    ДополнительныеПараметры - см. ПараметрыКонтактнойИнформации.
//                            - Строка - устарел.
//    УдалитьПоложениеЗаголовкаКИ - ПоложениеЗаголовкаЭлементаФормы - устарел, следует использовать ДополнительныеПараметры.
//    УдалитьИсключаемыеВиды - Массив  - устарел,следует использовать ДополнительныеПараметры.
//    УдалитьОтложеннаяИнициализация - Массив - устарел,следует использовать ДополнительныеПараметры.
//
Процедура ПриСозданииНаСервере(Форма, Объект, Знач ДополнительныеПараметры = Неопределено, УдалитьПоложениеЗаголовкаКИ = "",
	Знач УдалитьИсключаемыеВиды = Неопределено, УдалитьОтложеннаяИнициализация = Ложь) Экспорт
	
	ТипПомещения = Неопределено;
	Если ТипЗнч(ДополнительныеПараметры) = Тип("Структура") Тогда
		
		ДополнительныеПараметры.Свойство("ТипПомещения", ТипПомещения);
		ОтложеннаяИнициализация  = ?(ДополнительныеПараметры.Свойство("ОтложеннаяИнициализация"), ДополнительныеПараметры.ОтложеннаяИнициализация, Ложь);
		ПоложениеЗаголовкаКИ     = ?(ДополнительныеПараметры.Свойство("ПоложениеЗаголовкаКИ"), ДополнительныеПараметры.ПоложениеЗаголовкаКИ, "");
		ИсключаемыеВиды          = ?(ДополнительныеПараметры.Свойство("ИсключаемыеВиды"), ДополнительныеПараметры.ИсключаемыеВиды, Неопределено);
		СкрываемыеВиды           = ?(ДополнительныеПараметры.Свойство("СкрываемыеВиды"), ДополнительныеПараметры.СкрываемыеВиды, Неопределено);
		ИмяЭлементаДляРазмещения = ?(ДополнительныеПараметры.Свойство("ИмяЭлементаДляРазмещения"), ДополнительныеПараметры.ИмяЭлементаДляРазмещения, "ГруппаКонтактнаяИнформация");
		РазрешитьДобавлениеПолей = ?(ДополнительныеПараметры.Свойство("РазрешитьДобавлениеПолей"), ДополнительныеПараметры.РазрешитьДобавлениеПолей, Истина);
		РазмещеныНаФорме         = ?(ДополнительныеПараметры.Свойство("РазмещеныНаФорме"), ДополнительныеПараметры.РазмещеныНаФорме, Неопределено);
		ОбработкаНавигационнойСсылки = ?(ДополнительныеПараметры.Свойство("ОбработкаНавигационнойСсылки"), ДополнительныеПараметры.ОбработкаНавигационнойСсылки, Ложь);
	Иначе
		ИмяЭлементаДляРазмещения = ?(ДополнительныеПараметры = Неопределено, "ГруппаКонтактнаяИнформация", ДополнительныеПараметры);
		ОтложеннаяИнициализация  = УдалитьОтложеннаяИнициализация;
		ИсключаемыеВиды          = УдалитьИсключаемыеВиды;
		СкрываемыеВиды           = Неопределено;
		ПоложениеЗаголовкаКИ     = УдалитьПоложениеЗаголовкаКИ;
		РазрешитьДобавлениеПолей = Истина;
		РазмещеныНаФорме         = Неопределено;
		ОбработкаНавигационнойСсылки = Ложь;
	КонецЕсли;
	
	Если ИсключаемыеВиды = Неопределено Тогда
		ИсключаемыеВиды = Новый Массив;
	КонецЕсли;
		
	Если РазмещеныНаФорме = Неопределено Тогда
		РазмещеныНаФорме = Новый Соответствие;
		Для Каждого ИсключаемыйВид Из ИсключаемыеВиды Цикл
			РазмещеныНаФорме.Вставить(ИсключаемыйВид, Истина);
		КонецЦикла;
	Иначе
		РазмещеныНаФормеСсылки = Новый Соответствие();
		Виды = УправлениеКонтактнойИнформациейСлужебныйПовтИсп.ВидыКонтактнойИнформацииПоИмени();
		Для Каждого ЭлементНаФорме Из РазмещеныНаФорме Цикл
			Если ТипЗнч(ЭлементНаФорме.Ключ) = Тип("Строка") Тогда
				РазмещеныНаФормеСсылки.Вставить(Виды.Получить(ЭлементНаФорме.Ключ), Истина);
			Иначе	
				РазмещеныНаФормеСсылки.Вставить(ЭлементНаФорме.Ключ, Истина);
			КонецЕсли;
		КонецЦикла;
		РазмещеныНаФорме = РазмещеныНаФормеСсылки;
	КонецЕсли;
	
	Если СкрываемыеВиды = Неопределено Тогда
		СкрываемыеВиды = Новый Массив;
	КонецЕсли;
	
	ДобавляемыеРеквизиты = Новый Массив;
	ПроверитьНаличиеРеквизитовКонтактнойИнформации(Форма, ДобавляемыеРеквизиты);
	
	// Кэширование часто используемых значений
	СсылкаНаОбъект             = Объект.Ссылка;
	МетаданныеОбъекта          = СсылкаНаОбъект.Метаданные();
	ПолноеИмяОбъектаМетаданных = МетаданныеОбъекта.ПолноеИмя();
	ИмяОбъекта                 = МетаданныеОбъекта.Имя;
	ЭтоОсновнойЯзык            = ОбщегоНазначения.ЭтоОсновнойЯзык();
	
	НастройкиКИ = НастройкиПодсистемы(Объект.Ссылка);
	
	ГруппаВидовКонтактнойИнформации  = ГруппаВидовКонтактнойИнформацииОбъекта(ПолноеИмяОбъектаМетаданных);
	ИспользуетсяКонтактнаяИнформация = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ГруппаВидовКонтактнойИнформации, "Используется");
	Если ИспользуетсяКонтактнаяИнформация = Ложь Тогда
		
		ПараметрыВыводаКонтактнойИнформации = Новый Структура();
		ПараметрыВыводаКонтактнойИнформации.Вставить("ИмяЭлементаДляРазмещения", ИмяЭлементаДляРазмещения);
		ПараметрыВыводаКонтактнойИнформации.Вставить("ПоложениеЗаголовкаКИ", ПоложениеЗаголовкаКИ);
		ПараметрыВыводаКонтактнойИнформации.Вставить("ОтложеннаяИнициализация", ОтложеннаяИнициализация);
		ПараметрыВыводаКонтактнойИнформации.Вставить("ИсключаемыеВиды", ИсключаемыеВиды);
		ПараметрыВыводаКонтактнойИнформации.Вставить("СкрываемыеВиды", СкрываемыеВиды);
		ПараметрыВыводаКонтактнойИнформации.Вставить("СсылкаНаОбъект", СсылкаНаОбъект);
		ПараметрыВыводаКонтактнойИнформации.Вставить("ОписаниеКоманд", НастройкиКИ.ОписаниеКоманд);
		ПараметрыВыводаКонтактнойИнформации.Вставить("ОтображатьИконки", НастройкиКИ.ОтображатьИконки);
		ПараметрыВыводаКонтактнойИнформации.Вставить("РазмещеныНаФорме", РазмещеныНаФорме);
		ПараметрыВыводаКонтактнойИнформации.Вставить("РазрешитьДобавлениеПолей", РазрешитьДобавлениеПолей);
		ПараметрыВыводаКонтактнойИнформации.Вставить("ОбработкаНавигационнойСсылки", ОбработкаНавигационнойСсылки);
		ПараметрыВыводаКонтактнойИнформации.Вставить("ПоложениеКнопкиДобавить", НастройкиКИ.ПоложениеКнопкиДобавить);
		ПараметрыВыводаКонтактнойИнформации.Вставить("ШиринаПоляКомментарий", НастройкиКИ.ШиринаПоляКомментарий);
		
		СкрытьКонтактнуюИнформацию(Форма, ДобавляемыеРеквизиты, ПараметрыВыводаКонтактнойИнформации);
		
		Возврат;
	КонецЕсли;
	
	СодержитДействуетС = УправлениеКонтактнойИнформациейСлужебныйПовтИсп.КонтактнаяИнформацияОбъектаСодержитКолонкуДействуетС(СсылкаНаОбъект);
	РеквизитыОбъекта           = МетаданныеОбъекта.ТабличныеЧасти.КонтактнаяИнформация.Реквизиты;
	ЕстьКолонкаИдентификаторСтрокиТабличнойЧасти = (РеквизитыОбъекта.Найти("ИдентификаторСтрокиТабличнойЧасти") <> Неопределено);
	
	Если ОбщегоНазначения.ЭтоСсылка(ТипЗнч(Объект)) Тогда
		ТекстЗапроса = "ВЫБРАТЬ
		|	КонтактнаяИнформация.Представление КАК Представление,
		|	КонтактнаяИнформация.НомерСтроки КАК НомерСтроки,
		|	КонтактнаяИнформация.Вид КАК Вид, 
		|	ЕСТЬNULL(ВидыКонтактнойИнформации.ХранитьИсториюИзменений, ЛОЖЬ) КАК ХранитьИсториюИзменений,
		|	КонтактнаяИнформация.ЗначенияПолей,
		|	КонтактнаяИнформация.Значение,
		|	"""" КАК ДействуетС,
		|	0 КАК ИдентификаторСтрокиТабличнойЧасти,
		|	ЛОЖЬ КАК ЭтоИсторическаяКонтактнаяИнформация
		|ИЗ
		|	&ПутьКТаблицеКонтактнойИнформации КАК КонтактнаяИнформация
		|		ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВидыКонтактнойИнформации КАК ВидыКонтактнойИнформации
		|			ПО (КонтактнаяИнформация.Вид = ВидыКонтактнойИнформации.Ссылка)
		|ГДЕ
		|	КонтактнаяИнформация.Ссылка = &Ссылка УПОРЯДОЧИТЬ ПО Вид, ДействуетС";

		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ПутьКТаблицеКонтактнойИнформации", ПолноеИмяОбъектаМетаданных + ".КонтактнаяИнформация");
		
		Если ЕстьКолонкаИдентификаторСтрокиТабличнойЧасти Тогда
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "0 КАК ИдентификаторСтрокиТабличнойЧасти",
			"ЕСТЬNULL(КонтактнаяИнформация.ИдентификаторСтрокиТабличнойЧасти, 0) КАК ИдентификаторСтрокиТабличнойЧасти");
		КонецЕсли;
		
		Если СодержитДействуетС Тогда
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, """"" КАК ДействуетС", "КонтактнаяИнформация.ДействуетС КАК ДействуетС");
		КонецЕсли;
		Запрос = Новый Запрос(ТекстЗапроса);
		Запрос.УстановитьПараметр("Ссылка", СсылкаНаОбъект);
		КонтактнаяИнформация = Запрос.Выполнить().Выгрузить();
	Иначе
		КонтактнаяИнформация = Объект.КонтактнаяИнформация.Выгрузить();
		
		Если СодержитДействуетС Тогда
			ТипБулево = Новый ОписаниеТипов("Булево");
			КонтактнаяИнформация.Колонки.Добавить("ХранитьИсториюИзменений", ТипБулево);
			КонтактнаяИнформация.Колонки.Добавить("ЭтоИсторическаяКонтактнаяИнформация", ТипБулево);
			КонтактнаяИнформация.Сортировать("Вид, ДействуетС");
			
			ВидыКИХранитьИсториюИзменений = ОбщегоНазначения.ЗначениеРеквизитаОбъектов(
				КонтактнаяИнформация.ВыгрузитьКолонку("Вид"), "ХранитьИсториюИзменений");
			
			Для каждого СтрокаКонтактнойИнформации Из КонтактнаяИнформация Цикл
				ХранитьИсториюИзменений = ВидыКИХранитьИсториюИзменений.Получить(СтрокаКонтактнойИнформации.Вид);
				СтрокаКонтактнойИнформации.ХранитьИсториюИзменений = ?(ХранитьИсториюИзменений <> Неопределено, ХранитьИсториюИзменений, Ложь);
			КонецЦикла;
		КонецЕсли;
	КонецЕсли;
	
	Если СодержитДействуетС Тогда
		ПредыдущийВид = Неопределено;
		Для каждого СтрокаКонтактнойИнформации Из КонтактнаяИнформация Цикл
			Если СтрокаКонтактнойИнформации.ХранитьИсториюИзменений
				И (ПредыдущийВид = Неопределено ИЛИ ПредыдущийВид <> СтрокаКонтактнойИнформации.Вид) Тогда
				Отбор = Новый Структура("Вид", СтрокаКонтактнойИнформации.Вид);
				НайденныеСтроки = КонтактнаяИнформация.НайтиСтроки(Отбор);
				ПоследняяДата = НайденныеСтроки.Получить(НайденныеСтроки.Количество() - 1).ДействуетС;
				Для каждого НайденнаяСтрока Из НайденныеСтроки Цикл
					Если НайденнаяСтрока.ДействуетС < ПоследняяДата Тогда
						НайденнаяСтрока.ЭтоИсторическаяКонтактнаяИнформация = Истина;
					КонецЕсли;
				КонецЦикла;
				ПредыдущийВид = СтрокаКонтактнойИнформации.Вид;
			КонецЕсли;
		КонецЦикла;
		ЕстьИсторическаяИнформация = Истина;
	Иначе
		ЕстьИсторическаяИнформация = Ложь;
	КонецЕсли;
	
	ТекстЗапроса = СформироватьТекстЗапроса(ЕстьКолонкаИдентификаторСтрокиТабличнойЧасти, ЕстьИсторическаяИнформация, ЭтоОсновнойЯзык);
	
	Запрос = Новый Запрос(ТекстЗапроса);
	Запрос.УстановитьПараметр("ТаблицаКонтактнойИнформации", КонтактнаяИнформация);
	Запрос.УстановитьПараметр("ГруппаВидовКИ", ГруппаВидовКонтактнойИнформации);
	Запрос.УстановитьПараметр("Владелец", СсылкаНаОбъект);
	Запрос.УстановитьПараметр("СкрываемыеВиды", СкрываемыеВиды);
	Если Не ЭтоОсновнойЯзык Тогда
		Запрос.УстановитьПараметр("ЭтоОсновнойЯзык", ЭтоОсновнойЯзык);
		Запрос.УстановитьПараметр("КодЯзыка", ТекущийЯзык().КодЯзыка);
	КонецЕсли;
	
	УстановитьПривилегированныйРежим(Истина);
	КонтактнаяИнформация = Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией).Строки;
	УстановитьПривилегированныйРежим(Ложь);
	
	КонвертацияКонтактнойИнформацииВJSON(КонтактнаяИнформация);
	
	КонтактнаяИнформация.Сортировать("РеквизитДопУпорядочивания, НомерСтроки");
	СоздатьРеквизитыКонтактнойИнформации(Форма, ДобавляемыеРеквизиты, ИмяОбъекта, РазмещеныНаФорме, КонтактнаяИнформация, 
		ОтложеннаяИнициализация, ОбработкаНавигационнойСсылки);
	
	ДополнительныеПараметры = ДополнительныеПараметрыВыводаКонтактнойИнформации(НастройкиКИ.ОписаниеКоманд,
		НастройкиКИ.ОтображатьИконки, РазмещеныНаФорме, РазрешитьДобавлениеПолей, ИсключаемыеВиды, СкрываемыеВиды);
	ДополнительныеПараметры.ПоложениеКнопкиДобавить = НастройкиКИ.ПоложениеКнопкиДобавить;
	ДополнительныеПараметры.ШиринаПоляКомментарий = НастройкиКИ.ШиринаПоляКомментарий;
	
	ПараметрыКонтактнойИнформации = ПараметрыВыводаКонтактнойИнформации(Форма, ИмяЭлементаДляРазмещения,
		ПоложениеЗаголовкаКИ, ОтложеннаяИнициализация, ДополнительныеПараметры);
	ПараметрыКонтактнойИнформации.Владелец                     = СсылкаНаОбъект;
	ПараметрыКонтактнойИнформации.ПараметрыАдреса.ТипПомещения = ТипПомещения;
	ПараметрыКонтактнойИнформации.ОбработкаНавигационнойСсылки = ОбработкаНавигационнойСсылки;
	
	Отбор = Новый Структура("Тип", Перечисления.ТипыКонтактнойИнформации.Адрес);
	КоличествоАдресов = КонтактнаяИнформация.НайтиСтроки(Отбор).Количество();
	
	// Создадим элементы на форме и заполним значения реквизитов.
	СозданныеЭлементы = ОбщегоНазначения.СкопироватьРекурсивно(РазмещеныНаФорме);
	ПредыдущийВид = Неопределено;
	
	Если ОбщегоНазначения.ЭтоМобильныйКлиент() Тогда
		Форма.Элементы[ИмяЭлементаДляРазмещения].ШрифтЗаголовка = ШрифтыСтиля.ВажнаяНадписьШрифт;
	КонецЕсли;
	
	ИмяГруппы = "ГруппаЗначенияКомандыКИ" + ИмяЭлементаДляРазмещения;
	ГруппаЗначенияКомандыКИ = Форма.Элементы.Найти(ИмяГруппы);
		
	Если ГруппаЗначенияКомандыКИ = Неопределено Тогда
		Родитель = Родитель(Форма, ИмяЭлементаДляРазмещения);
		ГруппаЗначенияКомандыКИ = Форма.Элементы.Добавить(ИмяГруппы, Тип("ГруппаФормы"), Родитель);
		ГруппаЗначенияКомандыКИ.Вид = ВидГруппыФормы.ОбычнаяГруппа;
		ГруппаЗначенияКомандыКИ.Заголовок = НСтр("ru='Значения контактной информации'");
		ГруппаЗначенияКомандыКИ.ОтображатьЗаголовок = Ложь;
		ГруппаЗначенияКомандыКИ.РазрешитьИзменениеСостава = Ложь;
		ГруппаЗначенияКомандыКИ.Отображение = ОтображениеОбычнойГруппы.Нет;
		ГруппаЗначенияКомандыКИ.Группировка = ГруппировкаПодчиненныхЭлементовФормы.Вертикальная;
		ГруппаЗначенияКомандыКИ.ГоризонтальноеПоложениеВГруппе = ГоризонтальноеПоложениеЭлемента.Право;
		ГруппаЗначенияКомандыКИ.РастягиватьПоГоризонтали = Ложь;
		ГруппаЗначенияКомандыКИ.Объединенная = Ложь;
	КонецЕсли;
			
	ИмяГруппы = "ГруппаЗначенияКИ" + ИмяЭлементаДляРазмещения;
	ГруппаЗначенияКИ = Форма.Элементы.Найти(ИмяГруппы);
	
	Если ГруппаЗначенияКИ = Неопределено Тогда
		ГруппаЗначенияКИ = Форма.Элементы.Добавить(ИмяГруппы, Тип("ГруппаФормы"), ГруппаЗначенияКомандыКИ);
		ГруппаЗначенияКИ.Вид = ВидГруппыФормы.ОбычнаяГруппа;
		ГруппаЗначенияКИ.Заголовок = НСтр("ru='Значения и команды контактной информации'");
		ГруппаЗначенияКИ.ОтображатьЗаголовок = Ложь;
		ГруппаЗначенияКИ.РазрешитьИзменениеСостава = Ложь;
		ГруппаЗначенияКИ.Отображение = ОтображениеОбычнойГруппы.Нет;
		ГруппаЗначенияКИ.Группировка = ГруппировкаПодчиненныхЭлементовФормы.Вертикальная;
	КонецЕсли;
		
	Для Каждого СтрокаКИ Из КонтактнаяИнформация Цикл
		
		ДанныеВидаКонтактнойИнформации = ОбщегоНазначения.СтрокаТаблицыЗначенийВСтруктуру(СтрокаКИ);
			
		Если СтрокаКИ.ЭтоРеквизитТабличнойЧасти Тогда
			СоздатьЭлементыТабличнойЧасти(Форма, ИмяОбъекта, ИмяЭлементаДляРазмещения, СтрокаКИ, ДанныеВидаКонтактнойИнформации);
			Продолжить;
		КонецЕсли;
		
		Если СтрокаКИ.ПометкаУдаления И ПустаяСтрока(СтрокаКИ.ЗначенияПолей) И ПустаяСтрока(СтрокаКИ.Значение) Тогда
			Продолжить;
		КонецЕсли;
		
		СозданныйЭлемент = ?(Не СтрокаКИ.ЭтоИсторическаяКонтактнаяИнформация,
			СозданныеЭлементы.Получить(СтрокаКИ.Вид), Неопределено);
		
		СозданныйЭлемент = СозданныеЭлементы.Получить(СтрокаКИ.Вид);
		Если СозданныйЭлемент <> Неопределено Тогда
			СозданныйЭлемент = СтрокаКИ.Вид;
		КонецЕсли;
		СтатическийЭлемент = СозданныйЭлемент <> Неопределено;
		ЭтоНовыйВидКИ      = (СтрокаКИ.Вид <> ПредыдущийВид);
		
		Если НЕ СтрокаКИ.ЭтоИсторическаяКонтактнаяИнформация  Тогда
			ПредыдущийВид = СтрокаКИ.Вид;
		КонецЕсли;
		
		Если НЕ СтрокаКИ.ОтображатьВсегда И ПустаяСтрока(СтрокаКИ.Значение) И НЕ СтатическийЭлемент Тогда
			Если ЭтоНовыйВидКИ И Не СтрокаКИ.ПометкаУдаления Тогда
				Вид = СтрокаКИ.Вид; // СправочникСсылка.ВидыКонтактнойИнформации
				ДанныеВидаКонтактнойИнформации.Вставить("Ссылка", СтрокаКИ.Вид);
				Если ОбщегоНазначения.ЭтоМобильныйКлиент() Тогда
					ПараметрыКонтактнойИнформации.СписокДобавляемыхЭлементов.Добавить(ДанныеВидаКонтактнойИнформации, Строка(Вид));
				Иначе
					КартинкаТипа = КартинкаТипаКонтактнойИнформации(ДанныеВидаКонтактнойИнформации.Тип);
					ПараметрыКонтактнойИнформации.СписокДобавляемыхЭлементов.Добавить(ДанныеВидаКонтактнойИнформации, Строка(Вид),,КартинкаТипа);
				КонецЕсли;
			КонецЕсли;
			Продолжить;
		КонецЕсли;
		
		Если ОтложеннаяИнициализация Тогда
			
			ДобавитьРеквизитВОписание(Форма, СтрокаКИ, ДанныеВидаКонтактнойИнформации, ЭтоНовыйВидКИ,, 
				СтатическийЭлемент, ИмяЭлементаДляРазмещения);
			Если СтатическийЭлемент Тогда
				ПодготовитьСтатическийЭлемент(Форма, СтрокаКИ, СозданныеЭлементы, СозданныйЭлемент,
					ПараметрыКонтактнойИнформации.ОтображатьИконки, ИмяЭлементаДляРазмещения);
			КонецЕсли;
			Продолжить;
		КонецЕсли;
		
		ДобавитьРеквизитВОписание(Форма, СтрокаКИ, ДанныеВидаКонтактнойИнформации, ЭтоНовыйВидКИ,, 
			НЕ СтрокаКИ.ЭтоИсторическаяКонтактнаяИнформация, ИмяЭлементаДляРазмещения);
		
		Если СтатическийЭлемент Тогда
			ПодготовитьСтатическийЭлемент(Форма, СтрокаКИ, СозданныеЭлементы, СозданныйЭлемент, 
				ПараметрыКонтактнойИнформации.ОтображатьИконки, ИмяЭлементаДляРазмещения);
		Иначе
			СледующаяСтрока = ?(СозданныеЭлементы.Количество() = 0, Неопределено,
				ОпределитьСледующуюСтроку(Форма, КонтактнаяИнформация, СтрокаКИ));
			
			Если НЕ СтрокаКИ.ЭтоИсторическаяКонтактнаяИнформация Тогда
				ДобавитьСтрокуКонтактнойИнформации(Форма, СтрокаКИ, ИмяЭлементаДляРазмещения, ЭтоНовыйВидКИ, КоличествоАдресов, СледующаяСтрока);
			КонецЕсли;
			
		КонецЕсли;
		
	КонецЦикла;
	
	ОбновитьКонтекстноеМеню(Форма, ИмяЭлементаДляРазмещения);
	
	Если ПравоДоступа("Изменение",Метаданные.Справочники.ВидыКонтактнойИнформации) Тогда
		ПараметрыКонтактнойИнформации.СписокДобавляемыхЭлементов.Добавить(Новый Структура("Ссылка",
			Справочники.ВидыКонтактнойИнформации.ПустаяСсылка()), НСтр("ru = 'Настроить...'"));
	КонецЕсли;
	
	Если Не ОтложеннаяИнициализация И РазрешитьДобавлениеПолей
		И Форма.ПараметрыКонтактнойИнформации[ИмяЭлементаДляРазмещения].СписокДобавляемыхЭлементов.Количество() > 0 Тогда
		ДобавитьКнопкуДополнительногоПоляКонтактнойИнформации(Форма, ИмяЭлементаДляРазмещения);
	Иначе
		ДобавитьПояснениеПоСбросуНастроекФормы(Форма, ИмяЭлементаДляРазмещения, ОтложеннаяИнициализация);
	КонецЕсли;
	
КонецПроцедуры

// Обработчик для события формы ПриЧтенииНаСервере.
// Вызывается из модуля формы объекта-владельца КИ при внедрении подсистемы.
//
// Параметры:
//    Форма  - ФормаКлиентскогоПриложения - форма объекта-владельца, предназначенная для вывода контактной информации.
//    Объект - СправочникСсылка
//           - ДокументСсылка
//           - СправочникОбъект
//           - ДокументОбъект - объект-владелец контактной информации.
//    ИмяЭлементаДляРазмещения - Строка - группа, куда будут размещены элементы контактной информации.
//
Процедура ПриЧтенииНаСервере(Форма, Объект, ИмяЭлементаДляРазмещения = "ГруппаКонтактнаяИнформация") Экспорт
	
	СписокРеквизитовФормы = Форма.ПолучитьРеквизиты();
	
	ПервыйЗапуск = Истина;
	Для Каждого Реквизит Из СписокРеквизитовФормы Цикл
		Если Реквизит.Имя = "ПараметрыКонтактнойИнформации" И ТипЗнч(Форма.ПараметрыКонтактнойИнформации) = Тип("Структура") Тогда
			ПервыйЗапуск = Ложь;
			Прервать;
		КонецЕсли;
	КонецЦикла;
	
	Если ПервыйЗапуск Тогда
		Возврат;
	КонецЕсли;
	
	Параметры = ПараметрыКонтактнойИнформацииФормы(Форма.ПараметрыКонтактнойИнформации, ИмяЭлементаДляРазмещения);
	
	СсылкаНаОбъект = Объект.Ссылка;
	МетаданныеОбъекта = СсылкаНаОбъект.Метаданные();
	ПолноеИмяОбъектаМетаданных = МетаданныеОбъекта.ПолноеИмя();
	ИмяГруппыВидовКИ = СтрЗаменить(ПолноеИмяОбъектаМетаданных, ".", "");
	ГруппаВидовКИ = ВидКонтактнойИнформацииПоИмени(ИмяГруппыВидовКИ);
	ИмяЭлементаДляРазмещения = Параметры.ГруппаДляРазмещения;
	
	ПоложениеЗаголовкаКИ = ?(ЗначениеЗаполнено(Параметры.ПоложениеЗаголовка), ПредопределенноеЗначение(Параметры.ПоложениеЗаголовка), ПоложениеЗаголовкаЭлементаФормы.Лево);
	ВыполненаОтложеннаяИнициализация = Параметры.ВыполненаОтложеннаяИнициализация;
	ОтложеннаяИнициализация = Параметры.ОтложеннаяИнициализация И Не ВыполненаОтложеннаяИнициализация;
	
	ИспользуетсяКонтактнаяИнформация = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ГруппаВидовКИ, "Используется");
	Если ИспользуетсяКонтактнаяИнформация = Ложь Тогда
		МассивУдаляемыхРеквизитов = Параметры.ДобавленныеРеквизиты;
	Иначе
		УдалитьКомандыИЭлементыФормы(Форма, ИмяЭлементаДляРазмещения);
		
		МассивУдаляемыхРеквизитов = Новый Массив;
		ИмяОбъекта = Объект.Ссылка.Метаданные().Имя;
		
		СтатическиеРеквизиты = ОбщегоНазначения.СкопироватьРекурсивно(Параметры.РазмещеныНаФорме);
		ИменаТабличныхЧастейПоВидамКИ = Неопределено;
		
		Отбор = Новый Структура("ИмяЭлементаДляРазмещения", ИмяЭлементаДляРазмещения);
		КонтактнаяИнформацияОписаниеДополнительныхРеквизитов = УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеКонтактнойИнформацииНаФорме(Форма).НайтиСтроки(Отбор);
		Для Каждого РеквизитФормы Из КонтактнаяИнформацияОписаниеДополнительныхРеквизитов Цикл
			
			Если РеквизитФормы.ЭтоРеквизитТабличнойЧасти Тогда
				
				Если ИменаТабличныхЧастейПоВидамКИ = Неопределено Тогда
					Отбор = Новый Структура("ЭтоРеквизитТабличнойЧасти", Истина);
					ВидыКИТабличнойЧасти = УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеКонтактнойИнформацииНаФорме(Форма).Выгрузить(Отбор, "Вид");
					// @skip-check query-in-loop - Выполняется только в одной итерации, при первом появлении реквизита табличной части
					ИменаТабличныхЧастейПоВидамКИ = ИменаТабличныхЧастейПоВидамКИ(ВидыКИТабличнойЧасти, ИмяОбъекта);
				КонецЕсли;
				
				ИмяТабличнойЧасти = ИменаТабличныхЧастейПоВидамКИ[РеквизитФормы.Вид];
				МассивУдаляемыхРеквизитов.Добавить("Объект." + ИмяТабличнойЧасти + "." + РеквизитФормы.ИмяРеквизита);
				МассивУдаляемыхРеквизитов.Добавить("Объект." + ИмяТабличнойЧасти + "." + РеквизитФормы.ИмяРеквизита + "Значение");
				
			ИначеЕсли НЕ РеквизитФормы.Свойство("ЭтоИсторическаяКонтактнаяИнформация")
				ИЛИ НЕ РеквизитФормы.ЭтоИсторическаяКонтактнаяИнформация Тогда
				
				СтатическийРеквизит = СтатическиеРеквизиты.Получить(РеквизитФормы.Вид);
				Если СтатическийРеквизит <> Неопределено Тогда
					СтатическийРеквизит = РеквизитФормы.Вид;
				КонецЕсли;
				
				Если СтатическийРеквизит = Неопределено Тогда // Реквизит создается динамически.
					Если Не ОтложеннаяИнициализация И ЗначениеЗаполнено(РеквизитФормы.ИмяРеквизита) Тогда
						МассивУдаляемыхРеквизитов.Добавить(РеквизитФормы.ИмяРеквизита);
						Если ДляТипаКонтактнойИнформацииЕстьПолеКомментарий(РеквизитФормы.Тип, Параметры.ОбработкаНавигационнойСсылки) Тогда
							МассивУдаляемыхРеквизитов.Добавить("Комментарий" + РеквизитФормы.ИмяРеквизита);
						КонецЕсли;	
					КонецЕсли;
				Иначе
					СтатическиеРеквизиты.Удалить(СтатическийРеквизит);
				КонецЕсли;
				
			КонецЕсли;
		КонецЦикла;
		Для Каждого РеквизитФормы Из КонтактнаяИнформацияОписаниеДополнительныхРеквизитов Цикл
			УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеКонтактнойИнформацииНаФорме(Форма).Удалить(РеквизитФормы);
		КонецЦикла;
	КонецЕсли;
	Форма.ИзменитьРеквизиты(, МассивУдаляемыхРеквизитов);
	
	ДополнительныеПараметры = ПараметрыКонтактнойИнформации();
	ЗаполнитьЗначенияСвойств(ДополнительныеПараметры, Параметры);
	ДополнительныеПараметры.ИмяЭлементаДляРазмещения = ИмяЭлементаДляРазмещения;
	ДополнительныеПараметры.ПоложениеЗаголовкаКИ = ПоложениеЗаголовкаКИ;
	ДополнительныеПараметры.ОтложеннаяИнициализация = ОтложеннаяИнициализация;
	ПриСозданииНаСервере(Форма, Объект, ДополнительныеПараметры);
	
	Параметры = ПараметрыКонтактнойИнформацииФормы(Форма.ПараметрыКонтактнойИнформации, ИмяЭлементаДляРазмещения);
	Параметры.ВыполненаОтложеннаяИнициализация = ВыполненаОтложеннаяИнициализация;
	
КонецПроцедуры

// Обработчик для события формы ПослеЗаписиНаСервере.
// Вызывается из модуля формы объекта-владельца КИ при внедрении подсистемы.
//
// Параметры:
//    Форма  - ФормаКлиентскогоПриложения - форма объекта-владельца, предназначенная для вывода контактной информации.
//    Объект - СправочникСсылка
//           - ДокументСсылка
//           - СправочникОбъект
//           - ДокументОбъект - объект-владелец контактной информации.
//
Процедура ПослеЗаписиНаСервере(Форма, Объект) Экспорт
	
	ИмяОбъекта = Объект.Ссылка.Метаданные().Имя;
	
	// Только для контактной информации в составе табличной части.
	Отбор = Новый Структура("ЭтоРеквизитТабличнойЧасти", Истина);
	СтрокиТабличнойЧасти = УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеКонтактнойИнформацииНаФорме(Форма).Выгрузить(Отбор);
	ИменаТабличныхЧастейПоВидамКИ = ИменаТабличныхЧастейПоВидамКИ(СтрокиТабличнойЧасти, ИмяОбъекта);
	
	Для Каждого СтрокаТаблицы Из СтрокиТабличнойЧасти Цикл
		ВидИнформации = СтрокаТаблицы.Вид;
		ИмяРеквизита = СтрокаТаблицы.ИмяРеквизита;
		ТабличнаяЧастьФормы = Форма.Объект[ИменаТабличныхЧастейПоВидамКИ[ВидИнформации]];
		
		Для Каждого СтрокаТабличнойЧастиФормы Из ТабличнаяЧастьФормы Цикл
			
			Отбор = Новый Структура;
			Отбор.Вставить("Вид", ВидИнформации);
			Отбор.Вставить("ИдентификаторСтрокиТабличнойЧасти", СтрокаТабличнойЧастиФормы.ИдентификаторСтрокиТабличнойЧасти);
			НайденныеСтроки = Объект.КонтактнаяИнформация.НайтиСтроки(Отбор);
			
			Если НайденныеСтроки.Количество() = 1 Тогда
				
				СтрокаКИ = НайденныеСтроки[0];
				СтрокаТабличнойЧастиФормы[ИмяРеквизита] = СтрокаКИ.Представление;
				СтрокаТабличнойЧастиФормы[ИмяРеквизита + "Значение"] = СтрокаКИ.Значение;
				
			КонецЕсли;
		КонецЦикла;
	КонецЦикла;
	
КонецПроцедуры

// Обработчик для события формы ОбработкаПроверкиЗаполненияНаСервере.
// Вызывается из модуля формы объекта-владельца КИ при внедрении подсистемы.
//
// Параметры:
//    Форма  - ФормаКлиентскогоПриложения - форма объекта-владельца, предназначенная для вывода контактной информации.
//    Объект - СправочникСсылка
//           - ДокументСсылка
//           - СправочникОбъект
//           - ДокументОбъект - объект-владелец контактной информации.
//    Отказ  - Булево - если Истина, то во время проверки были обнаружены ошибки.
//
Процедура ОбработкаПроверкиЗаполненияНаСервере(Форма, Объект, Отказ) Экспорт
	
	ПараметрыСеанса.ИнтерактивнаяПроверкаЗаполненияКонтактнойИнформации = Истина;
	
	ИмяОбъекта = Объект.Ссылка.Метаданные().Имя;
	УровеньОшибок = 0;
	ПредыдущийВид = Неопределено;
	
	ИменаТабличныхЧастейПоВидамКИ = Неопределено;
	
	Для Каждого СтрокаТаблицы Из УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеКонтактнойИнформацииНаФорме(Форма) Цикл
		
		ВидИнформации = СтрокаТаблицы.Вид;
		ТипИнформации = СтрокаТаблицы.Тип;
		Комментарий   = СтрокаТаблицы.Комментарий;
		ИмяРеквизита  = СтрокаТаблицы.ИмяРеквизита;
		СвойствоВидаИнформации = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ВидИнформации, "ОбязательноеЗаполнение, ВидРедактирования");
		ОбязательноеЗаполнение = СвойствоВидаИнформации.ОбязательноеЗаполнение;
		
		Если СтрокаТаблицы.ЭтоРеквизитТабличнойЧасти Тогда
			
			Если ИменаТабличныхЧастейПоВидамКИ = Неопределено Тогда
				Отбор = Новый Структура("ЭтоРеквизитТабличнойЧасти", Истина);
				ВидыКИТабличнойЧасти = УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеКонтактнойИнформацииНаФорме(Форма).Выгрузить(Отбор , "Вид");
				// @skip-check query-in-loop - Выполняется только в одной итерации, при первом появлении реквизита табличной части
				ИменаТабличныхЧастейПоВидамКИ = ИменаТабличныхЧастейПоВидамКИ(ВидыКИТабличнойЧасти, ИмяОбъекта);
			КонецЕсли;
			
			ИмяТабличнойЧасти = ИменаТабличныхЧастейПоВидамКИ[ВидИнформации];
			ТабличнаяЧастьФормы = Форма.Объект[ИмяТабличнойЧасти];
			
			Для Каждого СтрокаТабличнойЧастиФормы Из ТабличнаяЧастьФормы Цикл
				
				Представление = СтрокаТабличнойЧастиФормы[ИмяРеквизита];
				Поле = "Объект." + ИмяТабличнойЧасти + "[" + XMLСтрока((СтрокаТабличнойЧастиФормы.НомерСтроки - 1)) + "]." + ИмяРеквизита;
				
				Если ОбязательноеЗаполнение И ПустаяСтрока(Представление) И Не ВидИнформации.ПометкаУдаления Тогда
					
					ОбщегоНазначения.СообщитьПользователю(
					СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Поле ""%1"" не заполнено.'"), ВидИнформации.Наименование),,Поле);
					ТекущийУровеньОшибок = 2;
					
				Иначе
					
					Значение = СтрокаТабличнойЧастиФормы[ИмяРеквизита + "Значение"];
					
					ТекущийУровеньОшибок = ПроверитьЗаполнениеКонтактнойИнформации(Представление, Значение, ВидИнформации,
						ТипИнформации, ИмяРеквизита, , Поле);
					
					СтрокаТабличнойЧастиФормы[ИмяРеквизита] = Представление;
					СтрокаТабличнойЧастиФормы[ИмяРеквизита + "Значение"] = Значение;
					
				КонецЕсли;
				
				УровеньОшибок = ?(ТекущийУровеньОшибок > УровеньОшибок, ТекущийУровеньОшибок, УровеньОшибок);
				
			КонецЦикла;
			
		Иначе
			
			ЭлементФормы = Форма.Элементы.Найти(ИмяРеквизита);
			Если ЭлементФормы = Неопределено Или ВидИнформации.ПометкаУдаления Тогда
				Продолжить; // Элемент не был создан. Не была вызвана отложенная инициализация.
			КонецЕсли;
			
			Если (СвойствоВидаИнформации.ВидРедактирования = "Диалог"
				Или ТипИнформации = Перечисления.ТипыКонтактнойИнформации.ВебСтраница)
				И Не УправлениеКонтактнойИнформациейКлиентСервер.КонтактнаяИнформацияЗаполнена(Строка(Форма[ИмяРеквизита])) Тогда
				Представление = "";
			Иначе
				Представление = Форма[ИмяРеквизита];
			КонецЕсли;
			
			Если ВидИнформации <> ПредыдущийВид И ОбязательноеЗаполнение И ПустаяСтрока(Представление)
				И Не ЕстьДругиеЗаполненныеСтрокКИДанногоВида(Форма, СтрокаТаблицы, ВидИнформации) Тогда
				// И нет других строк с данными для видов КИ с множественными значениями.
				
				ОбщегоНазначения.СообщитьПользователю(
				СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Поле ""%1"" не заполнено.'"), ВидИнформации.Наименование),,, ИмяРеквизита);
				ТекущийУровеньОшибок = 2;
				
			Иначе
				
				ТекущийУровеньОшибок = ПроверитьЗаполнениеКонтактнойИнформации(Представление, СтрокаТаблицы.Значение,
					ВидИнформации, ТипИнформации, ИмяРеквизита, Комментарий);
				
			КонецЕсли;
			
			УровеньОшибок = ?(ТекущийУровеньОшибок > УровеньОшибок, ТекущийУровеньОшибок, УровеньОшибок);
			
		КонецЕсли;
		
		ПредыдущийВид = ВидИнформации;
		
	КонецЦикла;
	
	Если УровеньОшибок <> 0 Тогда
		Отказ = Истина;
	КонецЕсли;
	
КонецПроцедуры

// Обработчик для события формы ПередЗаписьюНаСервере.
// Вызывается из модуля формы объекта-владельца КИ при внедрении подсистемы.
//
// Параметры:
//    Форма  - ФормаКлиентскогоПриложения - форма объекта-владельца, предназначенная для вывода контактной информации.
//    Объект - СправочникОбъект
//           - ДокументСсылка - объект-владелец контактной информации.
//             ДанныеФормыСтруктура - Объект, содержащий табличную часть с контактной информацией. Поддерживает работу
//                              со скрываемыми видами контактной информации только для уже существующих объектов,
//                              из-за невозможности установить ссылку для нового объекта.
//    Отказ  - Булево - если Истина, то объект не был записан, т.к. во время записи возникли ошибки.
//
Процедура ПередЗаписьюНаСервере(Форма, Объект, Отказ = Ложь) Экспорт
	
	КонтактнаяИнформация = КонтактнаяИнформацияИзРеквизитовФормы(Форма, Объект);
	
	ЭтоПараметрыОсновногоОбъекта  = Истина;
	ПараметрыКонтактнойИнформации = Неопределено;
	СкрываемыеВиды                = Новый Массив;
	
	ОпределитьПараметрыКонтактнойИнформацииПоВладельцу(Форма, Объект, ПараметрыКонтактнойИнформации, ЭтоПараметрыОсновногоОбъекта, СкрываемыеВиды);
	
	Если Объект.Ссылка.Пустая() И ТипЗнч(Объект) <> Тип("ДанныеФормыСтруктура") Тогда
		
		Если ЭтоПараметрыОсновногоОбъекта Тогда
			
			НоваяСсылка = Объект.ПолучитьСсылкуНового();
			МенеджерОбъекта = ОбщегоНазначения.МенеджерОбъектаПоСсылке(Объект.Ссылка);
			Если НоваяСсылка = МенеджерОбъекта.ПустаяСсылка() Тогда
				Объект.УстановитьСсылкуНового(МенеджерОбъекта.ПолучитьСсылку());
			КонецЕсли;
			ПараметрыКонтактнойИнформации.Владелец = Объект.ПолучитьСсылкуНового();
			
		Иначе
			Возврат;
		КонецЕсли;
		
	КонецЕсли;
	
	Если СкрываемыеВиды.Количество() = 0 Тогда
		Объект.КонтактнаяИнформация.Очистить();
	Иначе
		
		Индекс = Объект.КонтактнаяИнформация.Количество() -1;
		Пока Индекс >= 0 Цикл
			СтрокаТаблицы = Объект.КонтактнаяИнформация.Получить(Индекс);
			Если СкрываемыеВиды.Найти(СтрокаТаблицы.Вид) = Неопределено Тогда
				Объект.КонтактнаяИнформация.Удалить(СтрокаТаблицы);
			КонецЕсли;
			Индекс = Индекс - 1;
		КонецЦикла;
		
	КонецЕсли;
	
	УстановитьКонтактнуюИнформациюОбъекта(Объект, КонтактнаяИнформация);
	
КонецПроцедуры

// Добавляет (удаляет) поле ввода или комментарий на форму, обновляя данные.
// Вызывается из модуля формы объекта-владельца контактной информации.
//
// Параметры:
//    Форма     - ФормаКлиентскогоПриложения - форма объекта-владельца, предназначенная для вывода контактной информации.
//    Объект    - ДанныеФормыСтруктура - объект-владелец контактной информации.
//    Результат - Неопределено - служебный реквизит, полученный из предыдущего обработчика события.
//              - Структура: - набор свойств динамический:
//      * ПоменятьМестамиЭлементы - Булево - если значения элементов меняются местами.
//      * ПервыйЭлемент - Строка - если значения элементов меняются местами.
//      * ВторойЭлемент - Строка - если значения элементов меняются местами.
//      * ОбновитьКонтекстноеМеню - Булево -  если выполняется обновление меню
//      * ИмяРеквизита - Строка - если выполняется обновление меню
//      * ДобавляемыйВид - Булево - при добавлении нового элемента
//      * ЭтоДобавлениеКомментария - Булево - при добавлении комментария
//      * ОбновитьКонтекстноеМеню - Булево - при обновлении контекстного меню
//      * ИмяЭлементаДляРазмещения - Строка -  если добавляет новый элемент, комментарий или обновляется контекстное меню
//      * Комментарий - Строка - при обновлении контекстного меню
//       * Перечитать  - Булево - если нужно полностью обновить контактную информацию в рамках элемента для размещения.
//
// Возвращаемое значение:
//    Неопределено - значение не используется, обратная совместимость.
//
Функция ОбновитьКонтактнуюИнформацию(Форма, Объект, Результат = Неопределено) Экспорт
	
	Если Результат = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Если Результат.Свойство("ЭтоДобавлениеКомментария") Тогда
		ИзменитьКомментарий(Форма, Результат.ИмяРеквизита, Результат.ИмяЭлементаДляРазмещения, Результат.ТипКонтактнойИнформации);
	ИначеЕсли Результат.Свойство("ДобавляемыйВид") Тогда
		ДобавитьСтрокуКонтактнойИнформации(Форма, Результат, Результат.ИмяЭлементаДляРазмещения);	
	ИначеЕсли Результат.Свойство("ПоменятьМестамиЭлементы") Тогда
		
		Отбор = Новый Структура("ИмяРеквизита", Результат.ПервыйЭлемент);
		ОписаниеКонтактнойИнформации = УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеКонтактнойИнформацииНаФорме(Форма);
		ПервыйЭлемент = ОписаниеКонтактнойИнформации.НайтиСтроки(Отбор)[0];
		Отбор = Новый Структура("ИмяРеквизита", Результат.ВторойЭлемент);
		ВторойЭлемент = ОписаниеКонтактнойИнформации.НайтиСтроки(Отбор)[0];
		
		СписокПереносимыхСвойств = "Комментарий,Представление,Значение";
		ВременныйБуфер = Новый Структура(СписокПереносимыхСвойств);
		
		ЗаполнитьЗначенияСвойств(ВременныйБуфер, ПервыйЭлемент);
		ЗаполнитьЗначенияСвойств(ПервыйЭлемент, ВторойЭлемент, СписокПереносимыхСвойств);
		ЗаполнитьЗначенияСвойств(ВторойЭлемент, ВременныйБуфер);
		
		ПараметрыКонтактнойИнформации = ПараметрыКонтактнойИнформацииФормы(Форма.ПараметрыКонтактнойИнформации, 
			Результат.ИмяЭлементаДляРазмещения);
		ОбработкаНавигационнойСсылки = ПараметрыКонтактнойИнформации.ОбработкаНавигационнойСсылки;

		ЭтоАдресГиперссылкой = ПервыйЭлемент.Тип = Перечисления.ТипыКонтактнойИнформации.Адрес И ТипЗнч(
			Форма.Элементы[Результат.ПервыйЭлемент].РасширеннаяПодсказка.Заголовок) = Тип("ФорматированнаяСтрока");

		Если ПервыйЭлемент.Тип = Перечисления.ТипыКонтактнойИнформации.ВебСтраница И ОбработкаНавигационнойСсылки Тогда
			Форма[Результат.ПервыйЭлемент] = УправлениеКонтактнойИнформациейКлиентСервер.АдресСайта(
				ПервыйЭлемент.Представление, ПервыйЭлемент.Значение, Форма.ТолькоПросмотр);
			Форма[Результат.ВторойЭлемент] = УправлениеКонтактнойИнформациейКлиентСервер.АдресСайта(
				ВторойЭлемент.Представление, ВторойЭлемент.Значение, Форма.ТолькоПросмотр);
		ИначеЕсли ЭтоАдресГиперссылкой Тогда
			Форма[Результат.ПервыйЭлемент] = ?(ЗначениеЗаполнено(ПервыйЭлемент.Представление), ПервыйЭлемент.Представление,
				УправлениеКонтактнойИнформациейКлиентСервер.ТекстПустогоАдресаВВидеГиперссылки());
			Форма[Результат.ВторойЭлемент] =  ?(ЗначениеЗаполнено(ВторойЭлемент.Представление), ВторойЭлемент.Представление,
				УправлениеКонтактнойИнформациейКлиентСервер.ТекстПустогоАдресаВВидеГиперссылки());				
		Иначе
			Форма[Результат.ПервыйЭлемент] = ПервыйЭлемент.Представление;
			Форма[Результат.ВторойЭлемент] = ВторойЭлемент.Представление;
		КонецЕсли;
				
		Если ДляТипаКонтактнойИнформацииЕстьПолеКомментарий(ПервыйЭлемент.Тип, ОбработкаНавигационнойСсылки) Тогда
			Форма["Комментарий" + Результат.ПервыйЭлемент] = ПервыйЭлемент.Комментарий; 
			Форма["Комментарий" + Результат.ВторойЭлемент] = ВторойЭлемент.Комментарий;	
		ИначеЕсли ЭтоАдресГиперссылкой Тогда
		 	КомандыДляВывода = УправлениеКонтактнойИнформациейКлиентСервер.КомандыДляВыводаНаФорму(
				ПараметрыКонтактнойИнформации, ПервыйЭлемент.Тип, ПервыйЭлемент.Вид, ПервыйЭлемент.ХранитьИсториюИзменений);
			
			ПервыйЭлементКомментарий = Форма.Элементы[Результат.ПервыйЭлемент]; // ДекорацияФормы
			ПервыйЭлементКомментарий.РасширеннаяПодсказка.Заголовок = УправлениеКонтактнойИнформациейКлиентСервер.РасширеннаяПодсказкаАдреса(
				КомандыДляВывода, ПервыйЭлемент.Представление, ПервыйЭлемент.Комментарий);
			
			ВторойЭлементКомментарий = Форма.Элементы[Результат.ВторойЭлемент]; // ДекорацияФормы
			ВторойЭлементКомментарий.РасширеннаяПодсказка.Заголовок = УправлениеКонтактнойИнформациейКлиентСервер.РасширеннаяПодсказкаАдреса(
				КомандыДляВывода, ВторойЭлемент.Представление, ВторойЭлемент.Комментарий);
		Иначе	
			ПервыйЭлементКомментарий = Форма.Элементы[Результат.ПервыйЭлемент]; // ДекорацияФормы
			ПервыйЭлементКомментарий.РасширеннаяПодсказка.Заголовок = ПервыйЭлемент.Комментарий;
			ВторойЭлементКомментарий = Форма.Элементы[Результат.ВторойЭлемент]; // ДекорацияФормы
			ВторойЭлементКомментарий.РасширеннаяПодсказка.Заголовок = ВторойЭлемент.Комментарий;
		КонецЕсли;
		
	КонецЕсли;
	
	Если Результат.Свойство("ОбновитьКонтекстноеМеню") Тогда
		Если Результат.Свойство("ИмяЭлементаДляРазмещения") Тогда
			ОбновитьКонтекстноеМеню(Форма, Результат.ИмяЭлементаДляРазмещения);
			
			Если Результат.Свойство("ИмяРеквизита") Тогда
				ОписаниеКонтактнойИнформации = УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеКонтактнойИнформацииНаФорме(Форма);
				Отбор = Новый Структура("ИмяРеквизита", Результат.ИмяРеквизита);
				НайденнаяСтрока = ОписаниеКонтактнойИнформации.НайтиСтроки(Отбор)[0];
				Если УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВJSON(НайденнаяСтрока.Значение) Тогда
					КонтактнаяИнформацияПоПолям = УправлениеКонтактнойИнформациейСлужебный.JSONВКонтактнуюИнформациюПоПолям(НайденнаяСтрока.Значение, Неопределено);
					Если Результат.Свойство("Комментарий") Тогда
						КонтактнаяИнформацияПоПолям.Comment = Результат.Комментарий;
					Иначе 
						КонтактнаяИнформацияПоПолям.Comment = "";
					КонецЕсли;
					НайденнаяСтрока.Значение = УправлениеКонтактнойИнформациейСлужебный.СтруктураВСтрокуJSON(КонтактнаяИнформацияПоПолям);
				КонецЕсли;
			КонецЕсли;
			
		Иначе
			Для каждого ИмяЭлементаРазмещения Из Форма.ПараметрыКонтактнойИнформации Цикл
				ОбновитьКонтекстноеМеню(Форма, ИмяЭлементаРазмещения.Ключ);
			КонецЦикла;
		КонецЕсли;
	КонецЕсли;
	
	Если Результат.Свойство("Перечитать") И Результат.Свойство("ИмяЭлементаДляРазмещения") Тогда
		ПараметрыКонтактнойИнформации = ПараметрыКонтактнойИнформацииФормы(Форма.ПараметрыКонтактнойИнформации, 
		Результат.ИмяЭлементаДляРазмещения);
		
		ОписаниеКонтактнойИнформации = УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеКонтактнойИнформацииНаФорме(Форма);
		КопияОписанияКИ = ДанныеФормыВЗначение(ОписаниеКонтактнойИнформации, Тип("ТаблицаЗначений"));
				
		ПриЧтенииНаСервере(Форма, ПараметрыКонтактнойИнформации.Владелец, Результат.ИмяЭлементаДляРазмещения);
		
		ОписаниеКонтактнойИнформации = УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеКонтактнойИнформацииНаФорме(Форма);
		Для Каждого Строка Из ОписаниеКонтактнойИнформации Цикл
			Отбор = Новый Структура("ИмяРеквизита", Строка.ИмяРеквизита);
			НайденныеСтроки = КопияОписанияКИ.НайтиСтроки(Отбор);
			Если НайденныеСтроки.Количество() > 0 Тогда
				НайденнаяСтрока = НайденныеСтроки[0];
				Если Строка.Комментарий <> НайденнаяСтрока.Комментарий И ДляТипаКонтактнойИнформацииЕстьПолеКомментарий(
					Строка.Тип, ПараметрыКонтактнойИнформации.ОбработкаНавигационнойСсылки) Тогда
					Форма["Комментарий"+Строка.ИмяРеквизита] =  НайденнаяСтрока.Комментарий;
				КонецЕсли;	
				Если Строка.Значение <> НайденнаяСтрока.Значение Тогда
					Строка.Значение      =  НайденнаяСтрока.Значение;
					Строка.Представление =  НайденнаяСтрока.Представление;
					Строка.Комментарий   =  НайденнаяСтрока.Комментарий;
					Форма[Строка.ИмяРеквизита] = НайденнаяСтрока.Представление;
					ЭтоАдресГиперссылкой = Строка.Тип = Перечисления.ТипыКонтактнойИнформации.Адрес И ТипЗнч(
						Форма.Элементы[Строка.ИмяРеквизита].РасширеннаяПодсказка.Заголовок) = Тип("ФорматированнаяСтрока");
					Если ЭтоАдресГиперссылкой Тогда
						Форма[Строка.ИмяРеквизита] = ?(ЗначениеЗаполнено(НайденнаяСтрока.Представление),
							НайденнаяСтрока.Представление,
							УправлениеКонтактнойИнформациейКлиентСервер.ТекстПустогоАдресаВВидеГиперссылки());
							
						КомандыДляВывода = УправлениеКонтактнойИнформациейКлиентСервер.КомандыДляВыводаНаФорму(
							ПараметрыКонтактнойИнформации, Строка.Тип, Строка.Вид, Строка.ХранитьИсториюИзменений);		
						Форма.Элементы[Строка.ИмяРеквизита].РасширеннаяПодсказка.Заголовок = 
							УправлениеКонтактнойИнформациейКлиентСервер.РасширеннаяПодсказкаАдреса(
								КомандыДляВывода, Строка.Представление, Строка.Комментарий);	
					Иначе
						Форма[Строка.ИмяРеквизита] = НайденнаяСтрока.Представление;
						Форма.Элементы[Строка.ИмяРеквизита].РасширеннаяПодсказка.Заголовок = Строка.Комментарий;
					КонецЕсли;						
				КонецЕсли;
			КонецЕсли;			
		КонецЦикла;
		
	КонецЕсли;
		
	Возврат Неопределено;
	
КонецФункции

// Обработчик подписки события "ОбработкаЗаполнения".
//
// Параметры:
//  Источник             - СправочникОбъект
//                       - ДокументОбъект - объект, содержащий контактную информацию.
//  ДанныеЗаполнения     - Структура - данные с контактной информацией для заполнения объекта.
//  ТекстЗаполнения      - Строка - не используется.
//  СтандартнаяОбработка - Булево - не используется.
//
Процедура ОбработкаЗаполненияКонтактнойИнформации(Источник, ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка) Экспорт
	
	ОбработкаЗаполненияКонтактнойИнформацииОбъекта(Источник, ДанныеЗаполнения);
	
КонецПроцедуры

// Обработчик подписки события "ПередЗаписью" для обновления контактной информации для списков.
//
// Параметры:
//  Объект - Произвольный - объект, содержащий контактную информацию.
//  Отказ  - Булево       - не используется, обратная совместимость.
//
Процедура ОбработкаОбновленияКонтактнойИнформации(Объект, Отказ) Экспорт
	
	Если Объект.ОбменДанными.Загрузка Тогда
		Возврат;
	КонецЕсли;
	
	ОбновитьКонтактнуюИнформациюДляСписков(Объект);
	
КонецПроцедуры

// Обработчик подписки события "ОбработкаЗаполнения" для документов.
//
// Параметры:
//  Источник             - Произвольный         - объект, содержащий контактную информацию.
//  ДанныеЗаполнения     - Структура            - данные с контактной информацией для заполнения объекта.
//  ТекстЗаполнения      - Строка
//                       - Неопределено - данные заполнения реквизита Наименование.
//  СтандартнаяОбработка - Булево               - не используется.
//
Процедура ОбработкаЗаполненияКонтактнойИнформацииДокумента(Источник, ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка) Экспорт
	
	ОбработкаЗаполненияКонтактнойИнформацииОбъекта(Источник, ДанныеЗаполнения);
	
КонецПроцедуры

// Выполняет отложенную инициализацию реквизитов и элементов контактной информации.
//
// Параметры:
//  Форма                    - ФормаКлиентскогоПриложения - форма объекта-владельца, предназначенная для вывода
//                                                          контактной информации.
//  Объект                   - Произвольный - объект-владелец контактной информации.
//  ИмяЭлементаДляРазмещения - Строка - имя группы, где размещена контактная информация.
//
Процедура ВыполнитьОтложеннуюИнициализацию(Форма, Объект, ИмяЭлементаДляРазмещения = "ГруппаКонтактнаяИнформация") Экспорт
	
	КонтактнаяИнформацияЗаглушка = Форма.Элементы.Найти("КонтактнаяИнформацияЗаглушка"); // временный элемент
	Если КонтактнаяИнформацияЗаглушка <> Неопределено Тогда
		Форма.Элементы.Удалить(КонтактнаяИнформацияЗаглушка);
	КонецЕсли;
	
	ПараметрыКонтактнойИнформации = ПараметрыКонтактнойИнформацииФормы(Форма.ПараметрыКонтактнойИнформации, ИмяЭлементаДляРазмещения);
	
	КонтактнаяИнформацияОписаниеДополнительныхРеквизитов = УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеКонтактнойИнформацииНаФорме(Форма).Выгрузить(, "Вид, Представление, Значение, Комментарий");
	УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеКонтактнойИнформацииНаФорме(Форма).Очистить();
	
	ПоложениеЗаголовкаКИ = ?(ЗначениеЗаполнено(ПараметрыКонтактнойИнформации.ПоложениеЗаголовка), ПредопределенноеЗначение(ПараметрыКонтактнойИнформации.ПоложениеЗаголовка), ПоложениеЗаголовкаЭлементаФормы.Лево);
	
	ДополнительныеПараметрыКонтактнойИнформации = ПараметрыКонтактнойИнформации();
	ДополнительныеПараметрыКонтактнойИнформации.ИмяЭлементаДляРазмещения = ИмяЭлементаДляРазмещения;
	ДополнительныеПараметрыКонтактнойИнформации.ПоложениеЗаголовкаКИ = ПоложениеЗаголовкаКИ;
	ДополнительныеПараметрыКонтактнойИнформации.РазмещеныНаФорме = ПараметрыКонтактнойИнформации.РазмещеныНаФорме;
	
	ПриСозданииНаСервере(Форма, Объект, ДополнительныеПараметрыКонтактнойИнформации);
	ПараметрыКонтактнойИнформации = ПараметрыКонтактнойИнформацииФормы(Форма.ПараметрыКонтактнойИнформации, ИмяЭлементаДляРазмещения);
	
	Для Каждого ВидКонтактнойИнформации Из ПараметрыКонтактнойИнформации.РазмещеныНаФорме Цикл
		
		Отбор = Новый Структура("Вид", ВидКонтактнойИнформации.Ключ);
		МассивСтрок = УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеКонтактнойИнформацииНаФорме(Форма).НайтиСтроки(Отбор);
		
		Если МассивСтрок.Количество() > 0 Тогда
			СохраненноеЗначение = КонтактнаяИнформацияОписаниеДополнительныхРеквизитов.НайтиСтроки(Отбор)[0];
			ТекущееЗначение = МассивСтрок[0];
			ЗаполнитьЗначенияСвойств(ТекущееЗначение, СохраненноеЗначение);
			Форма[ТекущееЗначение.ИмяРеквизита] = СохраненноеЗначение.Представление;
		КонецЕсли;
	КонецЦикла;
	
	Если Форма.Элементы.Найти("ПустаяДекорацияКонтактнаяИнформация") <> Неопределено Тогда
		Форма.Элементы.ПустаяДекорацияКонтактнаяИнформация.Видимость = Ложь;
	КонецЕсли;
	
	ПараметрыКонтактнойИнформации.ВыполненаОтложеннаяИнициализация = Истина;
	
КонецПроцедуры

////////////////////////////////////////////////////////////////////////////////
// Вспомогательные функции и конструкторы.

// Возвращает используемые виды контактной информации объекта.
//
// Параметры:
//  ВладелецКонтактнойИнформации - СправочникСсылка.ВидыКонтактнойИнформации
//                               - СправочникОбъект.ВидыКонтактнойИнформации
//                               - ДанныеФормыСтруктура:
//                                 * Ссылка - СправочникСсылка.ВидыКонтактнойИнформации - ссылка на вид КИ.
//  ТипКонтактнойИнформации - ПеречислениеСсылка.ТипыКонтактнойИнформации - отбор видов КИ по типу.
//
// Возвращаемое значение:
//  ТаблицаЗначений - виды контактной информации, где:
//    * Ссылка  - СправочникСсылка.ВидыКонтактнойИнформации
//    * Тип - ПеречислениеСсылка.ТипыКонтактнойИнформации
//    * Представление - Строка
//    * Наименование - Строка
//    * РазрешитьВводНесколькихЗначений - Булево
//    * РеквизитДопУпорядочивания - Число
//    * ОбязательноеЗаполнение - Булево
//    * ПроверятьКорректность - Булево
//    * ИдентификаторДляФормул - Строка
//    * ИмяПредопределенногоВида - Строка
//
Функция ВидыКонтактнойИнформацииОбъекта(ВладелецКонтактнойИнформации, ТипКонтактнойИнформации = Неопределено) Экспорт
	
	Если ТипЗнч(ВладелецКонтактнойИнформации) = Тип("ДанныеФормыСтруктура") Тогда
		ТипСсылки = ТипЗнч(ВладелецКонтактнойИнформации.Ссылка)
	ИначеЕсли ОбщегоНазначения.ЭтоСсылка(ТипЗнч(ВладелецКонтактнойИнформации)) Тогда
		ТипСсылки = ТипЗнч(ВладелецКонтактнойИнформации);
	Иначе
		ТипСсылки = ТипЗнч(ВладелецКонтактнойИнформации.Ссылка)
	КонецЕсли;
	
	МетаданныеСправочника = Метаданные.НайтиПоТипу(ТипСсылки);
	Если МетаданныеСправочника <> Неопределено Тогда
		ГруппаВидовКИ = УправлениеКонтактнойИнформациейСлужебныйПовтИсп.ГруппаВидаКонтактнойИнформацииПоИмениОбъекта(
			МетаданныеСправочника.ПолноеИмя());
	Иначе
		ГруппаВидовКИ = Неопределено;
	КонецЕсли;
	
	Запрос = Новый Запрос;
	Запрос.Текст = "ВЫБРАТЬ
	|	ВидыКонтактнойИнформации.Ссылка,
	|	ВидыКонтактнойИнформации.Тип,
	|	ВидыКонтактнойИнформации.Представление,
	|	ВидыКонтактнойИнформации.Наименование,
	|	ВидыКонтактнойИнформации.РазрешитьВводНесколькихЗначений,
	|	ВидыКонтактнойИнформации.ОбязательноеЗаполнение,
	|	ВидыКонтактнойИнформации.ПроверятьКорректность,
	|	ВидыКонтактнойИнформации.ИдентификаторДляФормул,
	|	ВЫБОР КОГДА ВидыКонтактнойИнформации.ИмяПредопределенногоВида <> """"
	|		ТОГДА ВидыКонтактнойИнформации.ИмяПредопределенногоВида
	|		ИНАЧЕ ВидыКонтактнойИнформации.ИмяПредопределенныхДанных
	|	КОНЕЦ КАК ИмяПредопределенногоВида,
	|	ВидыКонтактнойИнформации.РеквизитДопУпорядочивания
	|ИЗ
	|	Справочник.ВидыКонтактнойИнформации КАК ВидыКонтактнойИнформации
	|ГДЕ
	|	ВидыКонтактнойИнформации.Родитель = &ГруппаВидовКИ
	|	И ВидыКонтактнойИнформации.ПометкаУдаления = ЛОЖЬ
	|	И ВидыКонтактнойИнформации.Используется = ИСТИНА
	|	И &ОтборТипаКонтактнойИнформации
	|
	|УПОРЯДОЧИТЬ ПО
	|	РеквизитДопУпорядочивания";
	
	Запрос.УстановитьПараметр("ГруппаВидовКИ", ГруппаВидовКИ);
	
	Если ТипКонтактнойИнформации <> Неопределено Тогда
		ТекстЗамены  = "ВидыКонтактнойИнформации.Тип = &ТипКонтактнойИнформации";
		Запрос.УстановитьПараметр("ТипКонтактнойИнформации", ТипКонтактнойИнформации);
	Иначе
		ТекстЗамены = "Истина";
	КонецЕсли;
	
	Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ОтборТипаКонтактнойИнформации", ТекстЗамены);
	
	РезультатЗапроса = Запрос.Выполнить().Выгрузить();
	Возврат РезультатЗапроса;
	
КонецФункции

// Возвращает признак, что объект подключен к подсистеме "Контактная информация"
// и содержит табличную часть КонтактнаяИнформация.
//
// Параметры:
//  ПроверяемыйОбъект - СправочникОбъект
//                    - СправочникСсылка
//                    - ДокументОбъект
//                    - ДокументСсылка
//                    - Тип - проверяемый объект на подключение к подсистеме Контактная информация.
//
// Возвращаемое значение:
//  Булево - если Истина, то объект содержит контактную информацию.
//
Функция СодержитКонтактнуюИнформацию(ПроверяемыйОбъект) Экспорт
	
	ТипОбъекта = ?(ТипЗнч(ПроверяемыйОбъект) <> Тип("Тип"),
		ТипЗнч(ПроверяемыйОбъект),
		ПроверяемыйОбъект);
	МетаданныеОбъекта = Метаданные.НайтиПоТипу(ТипОбъекта);
	Если МетаданныеОбъекта <> Неопределено
		И МетаданныеОбъекта.ТабличныеЧасти.Найти("КонтактнаяИнформация") <> Неопределено Тогда
			Возврат Истина;
	КонецЕсли;
	
	Возврат Ложь;
	
КонецФункции

// Возвращает ссылку на вид контактной информации.
// Если по виден не был найден по имени, то выполняется поиск по именам предопределенных элементов.
//
// Параметры:
//  Имя - Строка - уникальное имя вида контактной информации.
// 
// Возвращаемое значение:
//  СправочникСсылка.ВидыКонтактнойИнформации
//
Функция ВидКонтактнойИнформацииПоИмени(Имя) Экспорт
	
	Вид = Неопределено;
	Если Не ОбновлениеИнформационнойБазы.ВыполняетсяОбновлениеИнформационнойБазы() Тогда
		Виды = УправлениеКонтактнойИнформациейСлужебныйПовтИсп.ВидыКонтактнойИнформацииПоИмени();
		Вид = Виды.Получить(Имя);
	Иначе
		Виды = ПредопределенныеВидыКонтактнойИнформации(Имя);
		Если Виды.Количество() > 0 Тогда
			Вид = Виды[0].Ссылка;
		КонецЕсли;
	КонецЕсли;
	
	Если Вид <> Неопределено Тогда
		Возврат Вид;
	КонецЕсли;
	
	Возврат Справочники.ВидыКонтактнойИнформации[Имя];
	
КонецФункции

// Описание параметров контактной информации, используемых в обработчике ПриСозданииНаСервере.
// 
// Возвращаемое значение:
//  Структура - параметры контактной информации:
//   * Индекс                   - Строка - индекс адреса.
//   * Страна                   - Строка - страна адреса.
//   * ТипПомещения             - Строка - наименование  типа помещения, который будет установлен
//                                         в форме ввода нового адреса. По умолчанию, "Квартира".
//   * ИмяЭлементаДляРазмещения - Строка - группа, куда будут размещены элементы контактной информации.
//   * СкрываемыеВиды           - Массив - виды контактной информации, которые не требуется отображать на форме.
//   * ОтложеннаяИнициализация  - Булево - если Истина, то создание полей контактной информации на форме будет отложено.
//   * ПоложениеЗаголовкаКИ     - ПоложениеЗаголовкаЭлементаФормы - может принимать значения:
//                                                             ПоложениеЗаголовкаЭлементаФормы.Верх  или
//                                                             ПоложениеЗаголовкаЭлементаФормы.Лево (по умолчанию).
//   * РазрешитьДобавлениеПолей - Булево - если Истина, то на форме владельца контактной информации, будет отображена кнопка
//                                         для добавления дополнительной контактной информации
//   * РазмещеныНаФорме         - Соответствие из КлючИЗначение - виды контактной информации, которые были размещены на
//                                               форме интерактивно, при отложенной инициализации будут созданы на форме
//                                               после вызова процедуры УправлениеКонтактнойИнформацией.ВыполнитьОтложеннуюИнициализацию:
//                                  ** Ключ - Строка - имя предопределенного вида контактной информации
//                                          - СправочникСсылка.ВидыКонтактнойИнформации
//                                  ** Значение - Булево - Истина
//   * ОбработкаНавигационнойСсылки - Булево - если истина, то отображение контактной информации с типом ВебСтраница 
//   										   будет в виде гиперссылки	
//   * ИсключаемыеВиды - Массив - устарело. Следует использовать РазмещеныНаФорме. 						                                                            
//
Функция ПараметрыКонтактнойИнформации() Экспорт

	Результат = Новый Структура;
	Результат.Вставить("ТипПомещения", "Квартира");
	Результат.Вставить("Индекс", Неопределено);
	Результат.Вставить("Страна", Неопределено);
	Результат.Вставить("ОтложеннаяИнициализация", Ложь);
	Результат.Вставить("ПоложениеЗаголовкаКИ", "");
	Результат.Вставить("СкрываемыеВиды", Неопределено);
	Результат.Вставить("ИмяЭлементаДляРазмещения", "ГруппаКонтактнаяИнформация");
	Результат.Вставить("ОбработкаНавигационнойСсылки", Ложь); 
	Результат.Вставить("РазрешитьДобавлениеПолей", Истина);
	Результат.Вставить("РазмещеныНаФорме", Неопределено);
	Результат.Вставить("ИсключаемыеВиды", Неопределено);
	
	Возврат Результат;

КонецФункции 

////////////////////////////////////////////////////////////////////////////////
// Проверка и сведения об адресе

// Проверяет контактную информацию.
//
// Параметры:
//   Представление  - Строка - представление контактной информации. Используется, если невозможно определить
//                           представление из параметра ЗначенияПолей (отсутствие поля Представление).
//   ЗначенияПолей  - Строка
//                  - Структура
//                  - Соответствие
//                  - СписокЗначений - описание полей контактной информации.
//   ВидИнформации  - СправочникСсылка.ВидыКонтактнойИнформации - используется для определения типа, если его невозможно
//                                                               определить по параметру ЗначенияПолей.
//   ТипИнформации  - ПеречислениеСсылка.ТипыКонтактнойИнформации - тип контактной информации.
//   ИмяРеквизита   - Строка - имя реквизита на форме.
//   Комментарий    - Строка - текст комментария.
//   ПутьКРеквизиту - Строка - путь к реквизиту.
// 
// Возвращаемое значение:
//   Число - уровень ошибок, 0 - ошибки отсутствуют.
//
Функция ПроверитьКонтактнуюИнформацию(Представление, ЗначенияПолей, ВидИнформации, ТипИнформации,
	ИмяРеквизита, Комментарий = Неопределено, ПутьКРеквизиту = "") Экспорт
	
	ТекстСериализации = ?(ПустаяСтрока(ЗначенияПолей), Представление, ЗначенияПолей);

	Если УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВXML(ТекстСериализации) Тогда
		ОбъектКИ = КонтактнаяИнформацияВJSON(ТекстСериализации);
	Иначе
		ОбъектКИ = ЗначенияПолей;
	КонецЕсли;
	
	// Проверка
	Если ТипИнформации = Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты Тогда
		УровеньОшибок = ОшибкиЗаполненияЭлектроннойПочты(ОбъектКИ, ВидИнформации, ИмяРеквизита, ПутьКРеквизиту);
	ИначеЕсли ТипИнформации = Перечисления.ТипыКонтактнойИнформации.Адрес Тогда
		УровеньОшибок = ОшибкиЗаполненияАдреса(ОбъектКИ, ВидИнформации, ИмяРеквизита);
	ИначеЕсли ТипИнформации = Перечисления.ТипыКонтактнойИнформации.Телефон Тогда
		УровеньОшибок = ОшибкиЗаполненияТелефона(ОбъектКИ, ВидИнформации, ИмяРеквизита);
	ИначеЕсли ТипИнформации = Перечисления.ТипыКонтактнойИнформации.Факс Тогда
		УровеньОшибок = ОшибкиЗаполненияТелефона(ОбъектКИ, ВидИнформации, ИмяРеквизита);
	ИначеЕсли ТипИнформации = Перечисления.ТипыКонтактнойИнформации.ВебСтраница Тогда
		УровеньОшибок = ОшибкиЗаполненияВебСтраницы(ОбъектКИ, ВидИнформации, ИмяРеквизита);
	Иначе
		// Другое (прочее) не проверяем.
		УровеньОшибок = 0;
	КонецЕсли;
	
	Возврат УровеньОшибок;
	
КонецФункции

////////////////////////////////////////////////////////////////////////////////
// Обновление информационной базы.

// Устанавливает свойства группы контактной информации.
//
// Параметры:
//    Параметры - Структура:
//        * Код    - Строка   - код вида контактной информации для идентификации элемента.
//        * Наименование - Строка - наименование вида контактной информации.
//        * Имя - Строка - имя предопределенного вида контактной информации;
//        * Используется - Булево - признак использования вида контактной информации. Значение по умолчанию Истина.
//
// Возвращаемое значение:
//   СправочникСсылка.ВидыКонтактнойИнформации - ссылка на группу.
//
Функция УстановитьСвойстваГруппыВидаКонтактнойИнформации(Параметры) Экспорт
	
	Объект = ОбъектВидаКонтактнойИнформации(Параметры.Имя, Истина);
	
	Объект.ИмяПредопределенногоВида = Параметры.Имя;
	Объект.Родитель                 = Параметры.Группа;
	Объект.Используется             = Параметры.Используется;
	
	Если ПустаяСтрока(Объект.ИмяПредопределенногоВида) Тогда
		Объект.ИмяПредопределенногоВида = Объект.ИмяПредопределенныхДанных;
	КонецЕсли;
	
	УстановитьНаименованиеВидаКонтактнойИнформации(Объект, Параметры.Наименование);
	
	ОбновлениеИнформационнойБазы.ЗаписатьОбъект(Объект);
	
	Возврат Объект.Ссылка;
	
КонецФункции

// Устанавливает свойства вида контактной информации.
// Примечание. При использовании параметра Порядок следует внимательно следить за уникальностью назначаемого значения.
//  Если после выполнения обновления значения порядка окажутся неуникальными в пределах группы, то настройка порядка
//  пользователем будет невозможна.
//  В общем случае рекомендуется не использовать этот параметр (порядок не изменится), либо заполнять его значением
//  0 (порядок будет назначен автоматически в подсистеме "Настройка порядка элементов" при выполнении процедуры).
//  Для размещения видов КИ в определенной последовательности относительно друг друга без явного размещения в начале
//  списка достаточно вызывать данную процедуру в нужной последовательности для каждого вида КИ с указанием порядка 0.
//  Если добавляется предопределенный вид КИ к уже существующим в ИБ, не рекомендуется назначать порядок в явном виде.
//
// Параметры:
//   Параметры - Структура - свойства вида контактной информации:
//      * Имя - Строка - имя предопределенного вида контактной информации;
//      * Наименование - Строка - наименование вида контактной информации;
//      * Вид - СправочникСсылка.ВидыКонтактнойИнформации
//            - Строка - ссылка на вид контактной информации или
//                       идентификатор предопределенного элемента.
//      * Тип - ПеречислениеСсылка.ТипыКонтактнойИнформации - тип контактной информации или его
//                                                                    идентификатор.
//      * Порядок - Число
//                - Неопределено - порядок вида контактной информации, положение в
//                                 списке относительно других элементов:
//                                 Неопределено - не переназначать;
//                                 0            - назначить автоматически;
//                                 Число > 0    - назначить указанный порядок.
//      * МожноИзменятьСпособРедактирования - Булево                - Истина, если есть возможность изменять способ
//                                                                      редактирования только в диалоге, Ложь - иначе.
//    * ВидРедактирования - Строка - определят вид редактирования значения. Варианты: "ПолеВводаИДиалог", "ПолеВвода", "Диалог".
//                                    Если "Диалог", то форме выводится гиперссылка с представлением контактной
//                                    информации, по нажатию на которую, открывается форма соответствующего типа КИ.
//                                    Свойство применимо только для контактной информации с типом: Адрес, Телефон, Факс.
//                                    Если "ПолеВвода", то на форме выводится поле ввода.
//                                    Если "ПолеВводаИДиалог", то доступен ввод в поле и в форме соответствующего типа КИ.
//      * ОбязательноеЗаполнение                                    - Булево - Истина, если требуется обязательное
//                                                                      заполнение поля, Ложь - иначе.
//      * РазрешитьВводНесколькихЗначений - Булево                  - признак возможности использования дополнительных
//                                                                      полей ввода для данного вида.
//      * ЗапретитьРедактированиеПользователем - Булево             - признак недоступности редактирования
//                                                                      пользователем свойства вида контактной
//                                                                      информации.
//      * ХранитьИсториюИзменений - Булево -                          признак хранения истории изменений вида
//                                                                      контактной информации.
//                                                                      Значение по умолчанию Ложь.
//      * Используется - Булево -                                     признак использования вида контактной информации.
//                                                                      Значение по умолчанию Истина.
//      * ВидПоляДругое - Строка -                                    внешний вид поля типа "Другое". Возможные значения:
//                                                                      МногострочноеШирокое, ОднострочноеШирокое, ОднострочноеУзкое.
//                                                                      Значение по умолчанию - ОднострочноеШирокое.
//      * РедактированиеТолькоВДиалоге - Булево - устарело. Следует использовать ВидРедактирования.
//                                                 Если Истина, то форме выводится гиперссылка с представлением контактной
//                                                 информации по нажатию на которую, открывается форма соответствующего
//                                                 типа КИ. Свойство применимо только для контактной информации с типом:
//                                                 Адрес, Телефон, Факс, ВебСтраница. Значение по умолчанию - Ложь.
//      * НастройкиПроверки - Неопределено - для типов Другое, ВебСтраница, Skype.
//                          - Структура - состав полей зависит от типа контактной информации:
//         ** ТолькоНациональныйАдрес - Булево - для типа Адрес. Если Истина, если возможен ввод только национальных адресов.
//         ** ПроверятьКорректность - Булево - для типа Адрес. Если Истина, если требуется запрещать пользователю записывать
//                                             некорректные адреса.
//         ** СкрыватьНеактуальныеАдреса - Булево - для типа Адрес. Если Истина, если не требуется показывать
//                                                  неактуальные адреса при
//                                                  вводе (только если ТолькоНациональныйАдрес = Истина).
//         ** ВключатьСтрануВПредставление - Булево - для типа Адрес. Если Истина, если требуется включать наименование
//                                                    страны в представление адреса.
//         ** ПроверятьКорректность - Булево - для типа АдресЭлектроннойПочты .Если Истина, если требуется запрещать
//                                             пользователю записывать некорректный адрес электронной почты.
//         ** ТелефонСДобавочнымНомером  - Булево - для типа Телефон или Факс. Если Истина, то телефон/факс содержит
//                                                  добавочный номер.
//         ** ВводитьНомерПоМаске - Булево - для типа Телефон или Факс. Если Истина, если требуется ввод телефона по маске.
//         ** МаскаНомераТелефона  - Строка - для типа Телефон или Факс. Содержит посимвольную строку маски
//                                           интерактивного ввода текста в поле. Формат маски соответствует
//                                           платформенной маске для поля ввода.
//         ** ЗапрещатьВводНекорректного - Булево - устарел. Все переданные значения игнорируются.
//                                                  для типа Адрес. Для запрета пользователю записывать некорректные адреса
//                                                  следует использовать параметр ПроверятьКорректность.
//         ** ЗапрещатьВводНекорректного - Булево - устарел. Все переданные значения игнорируются.
//                                                  Для типа АдресЭлектроннойПочты. Для запрета пользователю записывать
//                                                  некорректные адреса следует использовать параметр ПроверятьКорректность.
//
Процедура УстановитьСвойстваВидаКонтактнойИнформации(Параметры) Экспорт
	
	Если Не ЗначениеЗаполнено(Параметры.Вид) Тогда
		Объект = ОбъектВидаКонтактнойИнформации(Параметры.Имя);
	ИначеЕсли ТипЗнч(Параметры.Вид) = Тип("Строка") Тогда
		Объект = ОбъектВидаКонтактнойИнформации(Параметры.Вид);
	Иначе
		Объект = Параметры.Вид.ПолучитьОбъект();
	КонецЕсли;
	
	ОбновитьСтатусРегламентногоЗадания = (Объект.ИсправлятьУстаревшиеАдреса <> Параметры.ИсправлятьУстаревшиеАдреса);
	
	Если Параметры.РедактированиеТолькоВДиалоге Тогда
		Параметры.ВидРедактирования = "Диалог";
	КонецЕсли;
	
	ЗаполнитьЗначенияСвойств(Объект, Параметры, "Тип, МожноИзменятьСпособРедактирования,
	|ВидРедактирования, ОбязательноеЗаполнение, РазрешитьВводНесколькихЗначений, ОтображатьВсегда,
	|ЗапретитьРедактированиеПользователем, Используется, ХранитьИсториюИзменений ,МеждународныйФорматАдреса, ИсправлятьУстаревшиеАдреса");
	
	Если ЗначениеЗаполнено(Параметры.Имя) Тогда
		Объект.ИмяПредопределенногоВида = Параметры.Имя;
	КонецЕсли;
	
	Если ПустаяСтрока(Объект.ИмяПредопределенногоВида) Тогда
		Объект.ИмяПредопределенногоВида = Объект.ИмяПредопределенныхДанных;
	КонецЕсли;
	
	УстановитьНаименованиеВидаКонтактнойИнформации(Объект, Параметры.Наименование);
	
	Если ПустаяСтрока(Объект.Родитель) Тогда
		Объект.Родитель = Параметры.Группа;
	КонецЕсли;
	Объект.ИмяГруппы = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Объект.Родитель, "ИмяПредопределенногоВида");
	
	Если Параметры.Тип = Перечисления.ТипыКонтактнойИнформации.Другое Тогда
		Объект.ВидПоляДругое = Параметры.ВидПоляДругое;
	КонецЕсли;
	
	ПроверятьНастройки = ТипЗнч(Параметры.НастройкиПроверки) = Тип("Структура");
	НастройкиПроверки = НастройкиПроверкиПараметровКонтактнойИнформации(Параметры.Тип);
	
	Если ПроверятьНастройки Тогда
		Если Параметры.НастройкиПроверки.Свойство("ТелефонCДобавочнымНомером") 
		   И Параметры.НастройкиПроверки.ТелефонCДобавочнымНомером  Тогда
				НастройкиПроверки.ТелефонСДобавочнымНомером = Параметры.НастройкиПроверки.ТелефонCДобавочнымНомером;
		КонецЕсли;
		ЗаполнитьЗначенияСвойств(НастройкиПроверки, Параметры.НастройкиПроверки);
	КонецЕсли;
	
	Если ПроверятьНастройки И Параметры.Тип = Перечисления.ТипыКонтактнойИнформации.Адрес Тогда
		ЗаполнитьЗначенияСвойств(Объект, НастройкиПроверки);
	ИначеЕсли ПроверятьНастройки И Параметры.Тип = Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты Тогда
		УстановитьЗначенияРеквизитовПроверки(Объект, НастройкиПроверки);
	ИначеЕсли ПроверятьНастройки И Параметры.Тип = Перечисления.ТипыКонтактнойИнформации.Телефон Тогда
		Объект.ТелефонСДобавочнымНомером = НастройкиПроверки.ТелефонСДобавочнымНомером;
		Объект.МаскаНомераТелефона = НастройкиПроверки.МаскаНомераТелефона;
		Объект.ВводитьНомерПоМаске = НастройкиПроверки.ВводитьНомерПоМаске;
	Иначе
		УстановитьЗначенияРеквизитовПроверки(Объект);
	КонецЕсли;
	
	Результат = УправлениеКонтактнойИнформациейСлужебный.ПроверитьПараметрыВидаКонтактнойИнформации(Объект);
	
	Если Результат.ЕстьОшибки Тогда
		ВызватьИсключение Результат.ТекстОшибки;
	КонецЕсли;
	
	Если Параметры.Порядок <> Неопределено Тогда
		Объект.РеквизитДопУпорядочивания = Параметры.Порядок;
	КонецЕсли;
	
	ЗначениеИспользуетсяУГруппы = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Объект.Родитель, "Используется");
	Если ПустаяСтрока(Объект.ИдентификаторДляФормул) Тогда
		Объект.ИдентификаторДляФормул = Справочники.ВидыКонтактнойИнформации.УникальныйИдентификаторДляФормул(
				НаименованиеДляФормированияИдентификатора(Объект), Объект.Ссылка, Объект.Родитель);
	КонецЕсли;
	
	Если ЗначениеИспользуетсяУГруппы = Ложь И Объект.Используется Тогда
		
		НачатьТранзакцию();
		Попытка
			
			Блокировка = Новый БлокировкаДанных;
			ЭлементБлокировки = Блокировка.Добавить("Справочник.ВидыКонтактнойИнформации");
			ЭлементБлокировки.УстановитьЗначение("Ссылка", Объект.Родитель);
			Блокировка.Заблокировать();
			
			Родитель = Объект.Родитель.ПолучитьОбъект();
			Родитель.Используется = Истина;
			ОбновлениеИнформационнойБазы.ЗаписатьОбъект(Родитель);
			
			ОбновлениеИнформационнойБазы.ЗаписатьОбъект(Объект);
			ЗафиксироватьТранзакцию();
		Исключение
			ОтменитьТранзакцию();
			ВызватьИсключение;
		КонецПопытки;
		
	Иначе
		ОбновлениеИнформационнойБазы.ЗаписатьОбъект(Объект);
	КонецЕсли;
	
	Если ОбновитьСтатусРегламентногоЗадания Тогда
		Статус = ?(Объект.ИсправлятьУстаревшиеАдреса = Истина, Истина, Неопределено);
		УправлениеКонтактнойИнформациейСлужебный.УстановитьИспользованиеРегламентногоЗадания(Статус);
	КонецЕсли;
	
КонецПроцедуры

// Возвращает структуру параметров группы вида контактной информации.
//
// Параметры:
//    ГруппаКонтактнойИнформации - СправочникСсылка.ВидыКонтактнойИнформации- группа контактной информации.
//
// Возвращаемое значение:
//    Структура:
//        * Имя          - Строка - уникальное имя вида контактной информации.
//        * Наименование - Строка - наименование вида контактной информации.
//        * Группа - СправочникСсылка.ВидыКонтактнойИнформации - ссылка на группу(родителя) элемента справочника.
//        * Используется - Булево - признак использования вида контактной информации. Значение по умолчанию Истина.
//
Функция ПараметрыГруппыВидаКонтактнойИнформации(ГруппаКонтактнойИнформации = Неопределено) Экспорт
	
	Результат = ОписаниеОбщихПараметровВидаКонтактнойИнформации();
	
	Если ТипЗнч(ГруппаКонтактнойИнформации ) = Тип("СправочникСсылка.ВидыКонтактнойИнформации") Тогда
		Значения = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ГруппаКонтактнойИнформации, "ИмяПредопределенногоВида, ИмяПредопределенныхДанных, Родитель, Наименование, Используется");
		Результат.Имя = ?(ЗначениеЗаполнено(Значения.ИмяПредопределенногоВида), Значения.ИмяПредопределенногоВида, Значения.ИмяПредопределенныхДанных);
		Результат.Группа = Значения.Родитель;
		Результат.Наименование = Значения.Наименование;
		Результат.Используется = Значения.Используется;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Возвращает структуру параметров вида контактной информации для определенного типа.
// 
// Параметры:
//    ТипИлиВидКонтактнойИнформации - ПеречислениеСсылка.ТипыКонтактнойИнформации
//                                  - Строка - тип контактной информации,
//                                  - СправочникСсылка.ВидыКонтактнойИнформации- вид контактной информации для
//                                  заполнения свойства НастройкиПроверки.
//
// Возвращаемое значение:
//  Структура:
//   * Имя          - Строка - уникальное имя вида контактной информации.
//   * Наименование - Строка - наименование вида контактной информации.
//   * Вид - СправочникСсылка.ВидыКонтактнойИнформации
//         - Строка - ссылка на вид контактной информации или
//                    идентификатор предопределенного элемента.
//   * Группа - СправочникСсылка.ВидыКонтактнойИнформации - ссылка на группу(родителя) элемента справочника.
//   * Тип - ПеречислениеСсылка.ТипыКонтактнойИнформации - тип контактной информации или его идентификатор.
//   * Порядок - Число
//             - Неопределено - порядок вида контактной информации, положение в списке относительно других элементов.
//                              Неопределено - не переназначать;
//                              0            - назначить автоматически;
//                              Число > 0    - назначить указанный порядок.
//                              Примечание. При использовании параметра Порядок следует внимательно следить
//                              за уникальностью назначаемого значения. Если после выполнения обновления
//                              значения порядка окажутся неуникальными в пределах группы, то настройка
//                              порядка пользователем будет невозможна. В общем случае рекомендуется не
//                              использовать этот параметр (порядок не изменится), либо заполнять его
//                              значением 0 (порядок будет назначен автоматически в подсистеме "Настройка
//                              порядка элементов" при выполнении процедуры). Для размещения видов КИ в
//                              определенной последовательности относительно друг друга без явного
//                              размещения в начале списка достаточно вызывать данную процедуру в нужной
//                              последовательности для каждого вида КИ с указанием порядка 0. Если
//                              добавляется предопределенный вид КИ к уже существующим в ИБ, не
//                              рекомендуется назначать порядок в явном виде.
//     * МожноИзменятьСпособРедактирования - Булево -признак возможности изменения свойств вида контактной информации пользователем.
//                                                    Если Ложь, то в форме вида контактной информации свойства доступны
//                                                    только для просмотра. Значение по умолчанию - Ложь.
//     * ВидРедактирования - Строка - вид редактирования.
//     * ВидРедактирования - Строка - определят вид редактирования значения. Варианты: "ПолеВводаИДиалог", "ПолеВвода", "Диалог".
//                                    Если "Диалог", то форме выводится гиперссылка с представлением контактной
//                                    информации, по нажатию на которую, открывается форма соответствующего типа КИ.
//                                    Свойство применимо только для контактной информации с типом: Адрес, Телефон, Факс.
//                                    Если "ПолеВвода", то на форме выводится поле ввода.
//                                    Если "ПолеВводаИДиалог", то доступен ввод в поле и в форме соответствующего типа КИ.
//     * ХранитьИсториюИзменений     - Булево - признак возможности хранения истории контактной информации.
//                                              Хранение истории допускается, если признак ВидРедактирования = "Диалог"
//                                              равен Истина. Свойство применимо если табличная часть КонтактнаяИнформация
//                                              содержит реквизит ДействуетС. Значение по умолчанию - Ложь.
//     * ОбязательноеЗаполнение       - Булево - если Истина, то требуется обязательный ввод значения в поле 
//                                               контактной информации. Значение по умолчанию - Ложь.
//     * РазрешитьВводНесколькихЗначений - Булево       - признак возможности ввода нескольких значений для данного вида.
//                                                        Значение по умолчанию - Ложь.
//     * ЗапретитьРедактированиеПользователем - Булево - признак недоступности редактирования пользователем 
//                                                       вида контактной информации. Значение по умолчанию - Ложь.
//     * Используется - Булево - если Ложь, то вид контактной информации недоступен для использования пользователем.
//                               Такой вид не выводится в формах и списке видов контактной информации.
//                               Значение по умолчанию - Истина.
//     * МеждународныйФорматАдреса          - Булево - признак международного формата адреса. 
//                                                     Если Истина, то ввода всех адресов только в международном формате.
//                                                     Значение по умолчанию - Ложь.
//     * ВидПоляДругое                        - Строка - определяет внешний вид поля с типом Другое на форме.
//                                            Варианты: МногострочноеШирокое, ОднострочноеШирокое, ОднострочноеУзкое.
//                                            Свойство применимо только для контактной информации с типом: Другое.
//                                            Для вида КИ с типом Другое значение по умолчанию - "ОднострочноеШирокое",
//                                            иначе пустая строка.
//     * РедактированиеТолькоВДиалоге - Булево - устарело. Следует использовать ВидРедактирования.
//                                               Если Истина, то форме выводится гиперссылка с представлением контактной
//                                               информации по нажатию на которую, открывается форма соответствующего
//                                               типа КИ. Свойство применимо только для контактной информации с типом -
//                                               Адрес, Телефон, Факс, ВебСтраница. Значение по умолчанию - Ложь.
//     * НастройкиПроверки  - Неопределено - для типов Другое, ВебСтраница, Skype.
//                          - Структура - настройки проверки вида контактной информации: 
//       ** ТолькоНациональныйАдрес - Булево - для типа Адрес. Если Истина, то разрешается ввод только национальных адресов.
//                                               Изменение страны у адреса не допускается.
//       ** ПроверятьКорректность - Булево - для типа Адрес. Если Истина, то для национальных адресов доступен ввод
//                                           только адресов с разбивкой по полям проходящих проверку по адресному классификатору.
//                                           Допускается ввод адресов других стран в свободной форме,
//                                           если свойство ТолькоНациональныйАдрес = Ложь.
//                                           Значение по умолчанию - Ложь.
//       ** ВключатьСтрануВПредставление - Булево - для типа Адрес. если Истина, то Наименование страны всегда
//                                                  добавляется в представление адреса, даже когда другие поля адреса пустые.
//                                                  Значение по умолчанию - Ложь.
//       ** УказыватьОКТМО - Булево - для типа Адрес. признак возможности ручного ввода кода ОКМТО в форме ввода адреса.
//       ** ПроверятьКорректность - Булево - для типа АдресЭлектроннойПочты. Если Истина, то запрещается пользователю ввод 
//                                          некорректный адрес электронной почты. Значение по умолчанию - Ложь.
//       ** ТелефонСДобавочнымНомером - Булево - для типа Телефон и Факс. Если Истина, то в форме ввода телефона
//                                               доступен ввод добавочного номера. Значение по умолчанию - Истина.
//
Функция ПараметрыВидаКонтактнойИнформации(ТипИлиВидКонтактнойИнформации = Неопределено) Экспорт
	
	Если ТипЗнч(ТипИлиВидКонтактнойИнформации) = Тип("СправочникСсылка.ВидыКонтактнойИнформации") Тогда
		
		ПараметрыВида = ПараметрыИзВидаКонтактнойИнформации(ТипИлиВидКонтактнойИнформации);
		
	Иначе
		
		Если ТипЗнч(ТипИлиВидКонтактнойИнформации) = Тип("Строка") Тогда
			УстанавливаемыйТип = Перечисления.ТипыКонтактнойИнформации[ТипИлиВидКонтактнойИнформации];
		Иначе
			УстанавливаемыйТип = ТипИлиВидКонтактнойИнформации;
		КонецЕсли;
		
		ПараметрыВида = ОписаниеПараметровКонтактнойИнформации(УстанавливаемыйТип);
	КонецЕсли;
	
	Возврат ПараметрыВида;
	
КонецФункции

// Записывает контактную информацию из XML в поля табличной части Контактная информация объекта.
//
// Параметры:
//    Объект - СправочникОбъект - объект конфигурации, содержащий табличную часть контактная информация.
//    Значение - Строка - контактная информация в внутреннем формате JSON.
//    ВидИнформации - СправочникСсылка.ВидыКонтактнойИнформации - ссылка на вид контактной информации.
//    ТипИнформации - ПеречислениеСсылка.ТипыКонтактнойИнформации - тип контактной информации.
//    ИдентификаторСтроки - Число - идентификатор строки табличной части.
//    Дата - Дата - дата, с которой действует запись контактной информации,
//                  используется при хранении истории изменения контактной информации.
//
Процедура ЗаписатьКонтактнуюИнформацию(Объект, Знач Значение, ВидИнформации, ТипИнформации, ИдентификаторСтроки = 0, Дата = Неопределено) Экспорт
	
	Если ПустаяСтрока(Значение) Тогда
		Возврат;
	КонецЕсли;
	
	Если УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВXML(Значение) Тогда
		ОбъектКИ = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияВСтруктуруJSON(Значение, ТипИнформации);
	Иначе
		ОбъектКИ = УправлениеКонтактнойИнформациейСлужебный.JSONВКонтактнуюИнформациюПоПолям(Значение, ТипИнформации);
	КонецЕсли;
	
	Если Не УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияЗаполнена(ОбъектКИ) Тогда
		Возврат;
	КонецЕсли;
	
	НоваяСтрока = Объект.КонтактнаяИнформация.Добавить();
	НоваяСтрока.Представление = ОбъектКИ.Value;
	НоваяСтрока.Значение      = УправлениеКонтактнойИнформациейСлужебный.СтруктураВСтрокуJSON(ОбъектКИ);
	НоваяСтрока.Вид           = ВидИнформации;
	НоваяСтрока.Тип           = ТипИнформации;
	
	Если УправлениеКонтактнойИнформациейСлужебныйПовтИсп.ДоступенМодульЛокализации() Тогда
		МодульУправлениеКонтактнойИнформациейЛокализация = ОбщегоНазначения.ОбщийМодуль("УправлениеКонтактнойИнформациейЛокализация");
		НоваяСтрока.ЗначенияПолей = МодульУправлениеКонтактнойИнформациейЛокализация.КонтактнаяИнформацияИзJSONВXML(ОбъектКИ, ТипИнформации);
	КонецЕсли;
	
	Если ЗначениеЗаполнено(Дата) 
		И УправлениеКонтактнойИнформациейСлужебныйПовтИсп.КонтактнаяИнформацияОбъектаСодержитКолонкуДействуетС(Объект.Ссылка) Тогда
			НоваяСтрока.ДействуетС  = Дата;
	КонецЕсли;
	
	Если ЗначениеЗаполнено(ИдентификаторСтроки) Тогда
		НоваяСтрока.ИдентификаторСтрокиТабличнойЧасти = ИдентификаторСтроки;
	КонецЕсли;
	
	// Заполнение дополнительных реквизитов ТЧ.
	УправлениеКонтактнойИнформациейСлужебный.ЗаполнитьТехническиеПоляКонтактнойИнформации(НоваяСтрока, ОбъектКИ, ТипИнформации);
	
КонецПроцедуры

// Обновляет представление контактной информации в служебном поле ВидДляСписка,
// используемое для вывода ее в динамических списках и отчетах.
//
// Параметры:
//  Объект -ОпределяемыйТип.ВладелецКонтактнойИнформации - ссылка на объект конфигурации, содержащий табличную часть
//  контактная информация.
//
Процедура ОбновитьКонтактнуюИнформациюДляСписков(Объект = Неопределено) Экспорт
	
	Если Объект = Неопределено Тогда
		УправлениеКонтактнойИнформациейСлужебный.ОбновитьКонтактнуюИнформациюДляСписков();
	Иначе
		Если Объект.Метаданные().ТабличныеЧасти.КонтактнаяИнформация.Реквизиты.Найти("ВидДляСписка") <> Неопределено Тогда
			УправлениеКонтактнойИнформациейСлужебный.ОбновитьКонтактнуюИнформациюДляСписковДляОбъекта(Объект);
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

// Выполняет отложенное обновление контактной информации для списков.
//
// Параметры:
//  Параметры    - Структура - параметры обработчика обновления.
//  РазмерПорции - Число - размер порции обрабатываемых данных за один запуск.
//
Процедура ОбновитьКонтактнуюИнформациюДляСписковОтложенно(Параметры, РазмерПорции = 1000) Экспорт
	
	ОбъектыСВидомДляСписка = Неопределено;
	Параметры.Свойство("ОбъектыСВидомДляСписка", ОбъектыСВидомДляСписка);
	
	Если Параметры.ПрогрессВыполнения.ВсегоОбъектов = 0 Тогда
		// расчет количества
		Запрос = Новый Запрос;
		Запрос.Текст = 
		"ВЫБРАТЬ
		|	ВидыКонтактнойИнформации.Ссылка,
		|ВЫБОР
		|	КОГДА ВидыКонтактнойИнформации.ИмяПредопределенногоВида <> """"
		|	ТОГДА ВидыКонтактнойИнформации.ИмяПредопределенногоВида
		|	ИНАЧЕ ВидыКонтактнойИнформации.ИмяПредопределенныхДанных
		|КОНЕЦ КАК ИмяПредопределенногоВида
		|ИЗ
		|	Справочник.ВидыКонтактнойИнформации КАК ВидыКонтактнойИнформации
		|ГДЕ
		|	ВидыКонтактнойИнформации.ЭтоГруппа = ИСТИНА";
		
		РезультатЗапроса = Запрос.Выполнить();
		ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
		ОбъектыСВидомДляСписка = Новый Массив;
		ТекстЗапроса = "";
		Разделитель = "";
		
		ШаблонЗапроса = "ВЫБРАТЬ
		| КОЛИЧЕСТВО(ТаблицаСКонтактнойИнформацией.Ссылка) КАК Количество,
		| ТИПЗНАЧЕНИЯ(ТаблицаСКонтактнойИнформацией.Ссылка) КАК Ссылка
		|ИЗ
		| &ТаблицаСКонтактнойИнформацией КАК ТаблицаСКонтактнойИнформацией
		| СГРУППИРОВАТЬ ПО
		|	ТИПЗНАЧЕНИЯ(ТаблицаСКонтактнойИнформацией.Ссылка)";
		
		Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
			Если СтрНачинаетсяС(ВыборкаДетальныеЗаписи.ИмяПредопределенногоВида, "Справочник") Тогда
				ИмяОбъекта = Сред(ВыборкаДетальныеЗаписи.ИмяПредопределенногоВида, СтрДлина("Справочник") + 1);
				
				Если Метаданные.Справочники.Найти(ИмяОбъекта) <> Неопределено Тогда
					КонтактнаяИнформация = Метаданные.Справочники[ИмяОбъекта].ТабличныеЧасти.КонтактнаяИнформация;
					Если КонтактнаяИнформация.Реквизиты.Найти("ВидДляСписка") <> Неопределено Тогда
						ТекстЗапроса = ТекстЗапроса + Разделитель 
							+ СтрЗаменить(ШаблонЗапроса, "&ТаблицаСКонтактнойИнформацией", "Справочник." + ИмяОбъекта);
						Разделитель = " ОБЪЕДИНИТЬ ВСЕ ";
					КонецЕсли;
				КонецЕсли;
			ИначеЕсли СтрНачинаетсяС(ВыборкаДетальныеЗаписи.ИмяПредопределенногоВида, "Документ") Тогда
				ИмяОбъекта = Сред(ВыборкаДетальныеЗаписи.ИмяПредопределенногоВида, СтрДлина("Документ") + 1);
				
				Если Метаданные.Документы.Найти(ИмяОбъекта) <> Неопределено Тогда
					КонтактнаяИнформация = Метаданные.Документы[ИмяОбъекта].ТабличныеЧасти.КонтактнаяИнформация;
					Если КонтактнаяИнформация.Реквизиты.Найти("ВидДляСписка") <> Неопределено Тогда
						ТекстЗапроса = ТекстЗапроса + Разделитель 
							+ СтрЗаменить(ШаблонЗапроса, "&ТаблицаСКонтактнойИнформацией", "Документ." + ИмяОбъекта);
						Разделитель = " ОБЪЕДИНИТЬ ВСЕ ";
					КонецЕсли;
				КонецЕсли;
			КонецЕсли;
		КонецЦикла;
		
		Если ПустаяСтрока(ТекстЗапроса) Тогда
			Параметры.ОбработкаЗавершена = Ложь;
			Возврат;
		КонецЕсли;
		Запрос = Новый Запрос(ТекстЗапроса);
		РезультатЗапроса = Запрос.Выполнить().Выбрать();
		Количество = 0;
		ОбъектыСВидомДляСписка = Новый Массив;
		Пока РезультатЗапроса.Следующий() Цикл
			Количество = Количество + РезультатЗапроса.Количество;
			ОбъектыСВидомДляСписка.Добавить(РезультатЗапроса.Ссылка);
		КонецЦикла;
		Параметры.ПрогрессВыполнения.ВсегоОбъектов = Количество;
		Параметры.Вставить("ОбъектыСВидомДляСписка", ОбъектыСВидомДляСписка);
	КонецЕсли;
	
	Если ОбъектыСВидомДляСписка = Неопределено ИЛИ ОбъектыСВидомДляСписка.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;
	
	ПолноеИмяОбъектаСВидомДляСписка = Метаданные.НайтиПоТипу(ОбъектыСВидомДляСписка.Получить(0)).ПолноеИмя();
	ТекстЗапроса = "ВЫБРАТЬ ПЕРВЫЕ 1234
	|	КонтактнаяИнформация.Ссылка КАК Ссылка
	|ИЗ
	|	&КонтактнаяИнформация КАК КонтактнаяИнформация
	|
	|СГРУППИРОВАТЬ ПО
	|	КонтактнаяИнформация.Ссылка
	|
	|ИМЕЮЩИЕ
	|	СУММА(ВЫБОР
	|			КОГДА КонтактнаяИнформация.ВидДляСписка = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ПустаяСсылка)
	|				ТОГДА 0
	|				ИНАЧЕ 1
	|		КОНЕЦ) = 0";
	
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "1234", Формат(РазмерПорции, "ЧГ=0"));
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&КонтактнаяИнформация", ПолноеИмяОбъектаСВидомДляСписка + ".КонтактнаяИнформация");
	
	Запрос = Новый Запрос(ТекстЗапроса);
	РезультатЗапроса = Запрос.Выполнить().Выбрать();
	Количество = РезультатЗапроса.Количество();
	Если Количество > 0 Тогда
		
		Блокировка = Новый БлокировкаДанных();
		Блокировка.Добавить(ПолноеИмяОбъектаСВидомДляСписка);
		
		НачатьТранзакцию();
		Попытка
			Блокировка.Заблокировать();
			
			Пока РезультатЗапроса.Следующий() Цикл
				Объект = РезультатЗапроса.Ссылка.ПолучитьОбъект();
				ОбновитьКонтактнуюИнформациюДляСписков(Объект);
				ОбновлениеИнформационнойБазы.ЗаписатьДанные(Объект);
			КонецЦикла;
			
			ЗафиксироватьТранзакцию();
			
		Исключение
			ОтменитьТранзакцию();
			ВызватьИсключение;
		КонецПопытки;

		Если Количество < 1000 Тогда
			ОбъектыСВидомДляСписка.Удалить(0);
		КонецЕсли;
		Параметры.ПрогрессВыполнения.ОбработаноОбъектов = Параметры.ПрогрессВыполнения.ОбработаноОбъектов + Количество;
	Иначе
		ОбъектыСВидомДляСписка.Удалить(0);
	КонецЕсли;
	
	Если ОбъектыСВидомДляСписка.Количество() > 0 Тогда
		Параметры.ОбработкаЗавершена = Ложь;
	КонецЕсли;
	
	Параметры.Вставить("ОбъектыСВидомДляСписка", ОбъектыСВидомДляСписка);
	
КонецПроцедуры

// Удаляет информацию о соответствии элемента справочника виде контактной информации предопределенному значению,
// которое помечено как удаленное. Для однократного вызова в обработчиках обновления по отказу от предопределенных
// элементов справочника ВидыКонтактнойИнформации.
//
Процедура СнятьПризнакПредопределенныйДляВидовКонтактнойИнформации() Экспорт
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
	"ВЫБРАТЬ
	|	ВидыКонтактнойИнформации.Ссылка КАК ВидКИ,
	|	ВидыКонтактнойИнформации.ИмяПредопределенныхДанных КАК ИмяПредопределенныхДанных,
	|	ЕСТЬNULL(ВидыКонтактнойИнформации.Родитель.ИмяПредопределенныхДанных, """") КАК Группа,
	|	ВидыКонтактнойИнформации.ИмяПредопределенногоВида КАК ИмяПредопределенногоВида,
	|	ВидыКонтактнойИнформации.Предопределенный КАК Предопределенный
	|ИЗ
	|	Справочник.ВидыКонтактнойИнформации КАК ВидыКонтактнойИнформации";
	
	ВидыКонтактнойИнформации = Запрос.Выполнить().Выгрузить();
	ВидыКонтактнойИнформации.Индексы.Добавить("ИмяПредопределенногоВида");
	
	Блокировка = Новый БлокировкаДанных();
	Блокировка.Добавить("Справочник.ВидыКонтактнойИнформации");
	
	НачатьТранзакцию();
	Попытка
		
		Блокировка.Заблокировать();
		
		Для каждого Вид Из ВидыКонтактнойИнформации Цикл
			
			Если Не Вид.Предопределенный Или Не СтрНачинаетсяС(НРег(Вид.ИмяПредопределенныхДанных), "удалить") Тогда
				Продолжить;
			КонецЕсли;
			
			ИмяПредопределенногоВида = Сред(Вид.ИмяПредопределенныхДанных, СтрДлина("удалить") + 1);
			Если ВидыКонтактнойИнформации.Найти(ИмяПредопределенногоВида, "ИмяПредопределенногоВида") <> Неопределено Тогда
				Продолжить;
			КонецЕсли;
			
			ОбъектВидКИ = Вид.ВидКИ.ПолучитьОбъект();
			Если Не ОбъектВидКИ.ЭтоГруппа Тогда
				ОбъектВидКИ.ИмяГруппы = Сред(Вид.Группа, СтрДлина("удалить") + 1);
			КонецЕсли;
			
			ОбъектВидКИ.ИмяПредопределенногоВида = ИмяПредопределенногоВида;
			ОбъектВидКИ.ИмяПредопределенныхДанных = "";
			ОбновлениеИнформационнойБазы.ЗаписатьДанные(ОбъектВидКИ);
			
		КонецЦикла;
		ЗафиксироватьТранзакцию();
		
	Исключение
		
		ОтменитьТранзакцию();
		ВызватьИсключение;
		
	КонецПопытки;
	
КонецПроцедуры

#Область УстаревшиеПроцедурыИФункции

////////////////////////////////////////////////////////////////////////////////
// Обратная совместимость.

// Устарела. Следует использовать УправлениеКонтактнойИнформацией.КонтактнаяИнформацияПоПредставлению.
// Преобразует представление контактной информации в XML строку соответствующую структуре
// XDTO пакетам КонтактнаяИнформация и Адрес.
// Для адресов, введенных в свободной форме, корректное преобразование не гарантируется.
//
//  Параметры:
//      Представление - Строка  - строковое представление контактной информации, выводимое пользователю.
//      ОжидаемыйВид  - СправочникСсылка.ВидыКонтактнойИнформации
//                    - ПеречислениеСсылка.ТипыКонтактнойИнформации
//                    - Структура - вид или тип контактной информации.
//
// Возвращаемое значение:
//      Строка - контактная информация в виде XML, соответствующего структуре XDTO пакетов КонтактнаяИнформация и Адрес.
//
Функция КонтактнаяИнформацияXMLПоПредставлению(Представление, ОжидаемыйВид) Экспорт
	
	Если УправлениеКонтактнойИнформациейСлужебныйПовтИсп.ДоступенМодульЛокализации() Тогда
		МодульУправлениеКонтактнойИнформациейЛокализация = ОбщегоНазначения.ОбщийМодуль("УправлениеКонтактнойИнформациейЛокализация");
	
		Возврат МодульУправлениеКонтактнойИнформациейЛокализация.КонтактнаяИнформацияXDTOВXML(
			МодульУправлениеКонтактнойИнформациейЛокализация.КонтактнаяИнформацияXDTOПоПредставлению(Представление, ОжидаемыйВид));
			
	КонецЕсли;
	
	Возврат "";
	
КонецФункции

#КонецОбласти

// Возвращает описание команд, разбитое по типам контактной информации.
// Полученное соответствие используется в УправлениеКонтактнойИнформациейПереопределяемый.ПриОпределенииНастроек 
//
// Возвращаемое значение:
//   Соответствие из КлючИЗначение:
//     * Ключ     - ПеречислениеСсылка.ТипыКонтактнойИнформации
//     * Значение - см. КомандыТипаКонтактнойИнформации
//
Функция ОписаниеКоманд() Экспорт
	
	ОписаниеКоманд = Новый Соответствие;
	ОписаниеКоманд.Вставить(Перечисления.ТипыКонтактнойИнформации.Адрес, КомандыТипаКонтактнойИнформации(
		Перечисления.ТипыКонтактнойИнформации.Адрес));
	ОписаниеКоманд.Вставить(Перечисления.ТипыКонтактнойИнформации.Телефон, КомандыТипаКонтактнойИнформации(
		Перечисления.ТипыКонтактнойИнформации.Телефон));
	ОписаниеКоманд.Вставить(Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты,
		КомандыТипаКонтактнойИнформации(Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты));
	ОписаниеКоманд.Вставить(Перечисления.ТипыКонтактнойИнформации.Skype, КомандыТипаКонтактнойИнформации(
		Перечисления.ТипыКонтактнойИнформации.Skype));
	ОписаниеКоманд.Вставить(Перечисления.ТипыКонтактнойИнформации.ВебСтраница, КомандыТипаКонтактнойИнформации(
		Перечисления.ТипыКонтактнойИнформации.ВебСтраница));
	ОписаниеКоманд.Вставить(Перечисления.ТипыКонтактнойИнформации.Факс, КомандыТипаКонтактнойИнформации(
		Перечисления.ТипыКонтактнойИнформации.Факс));
	ОписаниеКоманд.Вставить(Перечисления.ТипыКонтактнойИнформации.Другое, КомандыТипаКонтактнойИнформации(
		Перечисления.ТипыКонтактнойИнформации.Другое));

	Возврат ОписаниеКоманд;
	
КонецФункции

// Возвращает описание команд, предназначенные для типа контактной информации, переданного в качестве параметра.
// Полученное соответствие используется в УправлениеКонтактнойИнформациейПереопределяемый.ПриОпределенииНастроек 
//
// Параметры:
//   Тип - ПеречислениеСсылка.ТипыКонтактнойИнформации
//
// Возвращаемое значение:
//   Структура - состав полей зависит от типа контактной информации. Для типа Адрес: ВвестиКомментарийКАдресу,
//   ПоказатьНаКартеЯндекс, ПоказатьНаКартеGoogle, ЗапланироватьВстречу, ПоказатьИсториюИзменений. 
//     Для типа Телефон: ПозвонитьПоТелефону, ОтправитьSMS, ПоказатьИсториюИзменений.
//     Для типа Факс: ОтправитьФакс, ПоказатьИсториюИзменений.
//     Для типа АдресЭлектронной почты: НаписатьЭлектронноеПисьмо.
//     Для типа Skype: ПозвонитьSkype, НачатьЧатSkype.
//     Для типа ВебСтраница: ОткрытьВебСтраницу.
//     Для типа Другое: ОткрытьОкноДругое.
//     Состав полей:
//     * ВвестиКомментарийКАдресу  - см. ОписаниеКомандыПоИмени
//     * ПоказатьНаКартеЯндекс     - см. ОписаниеКомандыПоИмени
//     * ПоказатьНаКартеGoogle     - см. ОписаниеКомандыПоИмени
//     * ЗапланироватьВстречу      - см. ОписаниеКомандыПоИмени
//     * ПоказатьИсториюИзменений  - см. ОписаниеКомандыПоИмени
//     * ПозвонитьПоТелефону       - см. ОписаниеКомандыПоИмени
//     * ОтправитьSMS              - см. ОписаниеКомандыПоИмени
//     * ОтправитьФакс             - см. ОписаниеКомандыПоИмени
//     * НаписатьЭлектронноеПисьмо - см. ОписаниеКомандыПоИмени
//     * ПозвонитьSkype            - см. ОписаниеКомандыПоИмени
//     * НачатьЧатSkype            - см. ОписаниеКомандыПоИмени
//     * ОткрытьВебСтраницу        - см. ОписаниеКомандыПоИмени
//     * ОткрытьОкноДругое         - см. ОписаниеКомандыПоИмени
//
Функция КомандыТипаКонтактнойИнформации(Тип) Экспорт

	Возврат УправлениеКонтактнойИнформациейСлужебныйПовтИсп.КомандыТипаКонтактнойИнформации(Тип);

КонецФункции

// Возвращает структуру с описанием команды контактной информации.
// Полученное соответствие используется в УправлениеКонтактнойИнформациейПереопределяемый.ПриОпределенииНастроек 
//
// Параметры:
//   ИмяКоманды - Строка - имя команды, описание которой нужно получить.
//
// Возвращаемое значение:
//   см. СвойстваКоманды 
//
Функция ОписаниеКомандыПоИмени(ИмяКоманды) Экспорт
	
	// Команда для типа Адрес, Телефон, Факс
	Если ИмяКоманды = "ПоказатьИсториюИзменений" Тогда
		Возврат СвойстваКоманды(
				НСтр("ru = 'История изменений...'"),
				НСтр("ru = 'Показывает историю изменения контактной информации'"),
				БиблиотекаКартинок.ИсторияИзменений,
				"УправлениеКонтактнойИнформациейКлиент.ПередОткрытиемФормыИсторииИзменений",
				Истина);
	КонецЕсли;
	
	// Команды для типа Адрес
	Если ИмяКоманды = "ВвестиКомментарийКАдресу" Тогда
		Возврат СвойстваКоманды(
				НСтр("ru = 'Ввести комментарий'"),
				НСтр("ru = 'Ввести комментарий'"),
				БиблиотекаКартинок.Комментарий,
				"УправлениеКонтактнойИнформациейКлиент.ПередВводомКомментария",
				Истина);
	ИначеЕсли ИмяКоманды = "ПоказатьНаКартеЯндекс" Тогда
		Возврат СвойстваКоманды(
				НСтр("ru = 'Адрес на Яндекс.Картах'"),
				НСтр("ru = 'Показывает адрес на картах Яндекс.Карты'"),
				БиблиотекаКартинок.ЯндексКарты,
				"УправлениеКонтактнойИнформациейКлиент.ПередПоказомАдресаНаКартеЯндекс");
	ИначеЕсли ИмяКоманды = "ПоказатьНаКартеGoogle" Тогда
		Возврат СвойстваКоманды(
				НСтр("ru = 'Адрес на Google Maps'"),
				НСтр("ru = 'Показывает адрес на карте Google Maps'"),
				БиблиотекаКартинок.GoogleMaps,
				"УправлениеКонтактнойИнформациейКлиент.ПередПоказомАдресаНаКартеGoogle");
	ИначеЕсли ИмяКоманды = "ЗапланироватьВстречу" Тогда
		Возврат СвойстваКоманды("", "");
	КонецЕсли;
	
	// Команды для типа Телефон
	Если ИмяКоманды = "ПозвонитьПоТелефону" Тогда
		Возврат СвойстваКоманды(
				НСтр("ru = 'Позвонить'"),
				НСтр("ru = 'Позвонить по телефону'"),
				БиблиотекаКартинок.Позвонить,
				"УправлениеКонтактнойИнформациейКлиент.ПередТелефоннымЗвонком");
	ИначеЕсли ИмяКоманды = "ОтправитьSMS" Тогда
		Возврат СвойстваКоманды(
				НСтр("ru = 'Отправить SMS'"),
				НСтр("ru = 'Отправить SMS'"),
				БиблиотекаКартинок.ОтправитьSMS,
				"УправлениеКонтактнойИнформациейКлиент.ПередСозданиемSMS");
	КонецЕсли;
	
	// Команды для типа Факс
	Если ИмяКоманды = "ОтправитьФакс" Тогда
		Возврат СвойстваКоманды("", "");
	КонецЕсли;
	
	// Команды для типа АдресЭлектроннойПочты
	Если ИмяКоманды = "НаписатьЭлектронноеПисьмо" Тогда
		Возврат СвойстваКоманды(
				НСтр("ru = 'Написать письмо'"),
				НСтр("ru = 'Написать письмо на указанный адрес'"),
				БиблиотекаКартинок.КонтактнаяИнформацияОтправитьЭлектронноеПисьмо,
				"УправлениеКонтактнойИнформациейКлиент.ПередСозданиемЭлектронногоПисьма");
	КонецЕсли;
	
	// Команды для типа Skype
	Если ИмяКоманды = "ПозвонитьSkype" Тогда
		Возврат СвойстваКоманды(
				НСтр("ru = 'Позвонить'"),
				НСтр("ru = 'Позвонить на Skype'"),
				БиблиотекаКартинок.Позвонить,
				"УправлениеКонтактнойИнформациейКлиент.ПередЗвонкомНаSkype");
	ИначеЕсли ИмяКоманды = "НачатьЧатSkype" Тогда
		Возврат СвойстваКоманды(
				НСтр("ru = 'Начать чат'"),
				НСтр("ru = 'Начать чат в Skype'"),
				БиблиотекаКартинок.ОтправитьSMS,
				"УправлениеКонтактнойИнформациейКлиент.ПередНачаломБеседыВSkype");
	КонецЕсли;
	
	// Команды для типа ВебСтраница
	Если ИмяКоманды = "ОткрытьВебСтраницу" Тогда
		Возврат СвойстваКоманды(
				НСтр("ru = 'Перейти'"),
				НСтр("ru = 'Перейти по ссылке'"),
				БиблиотекаКартинок.КонтактнаяИнформацияПерейтиПоСсылке,
				"УправлениеКонтактнойИнформациейКлиент.ПередПереходомПоВебСсылке");
	КонецЕсли;

	// Команды типа Другое
	Если ИмяКоманды = "ОткрытьОкноДругое" Тогда
		Возврат СвойстваКоманды("", "");
	КонецЕсли;
		
КонецФункции

// Возвращает структуру для описания команд контактной информации.
// Полученная структура используется в УправлениеКонтактнойИнформациейПереопределяемый.ПриОпределенииНастроек
//
// Параметры:
//   Заголовок - Строка   - заголовок команды.
//   Подсказка - Строка   - подсказка команды.
//   Картинка  - Картинка - картинка команды.
//   Действие  - Строка   - полный путь к процедуре, которую необходимо выполнить.
//                            Например, "_ДемоСтандартныеПодсистемыКлиент.ОткрытьФормуДокументаВстреча".
//   ИзменяетСохраняемыеДанные - Булево 
//
// Возвращаемое значение:
//   Структура:
//     * Заголовок - Строка
//     * Подсказка - Строка
//     * Картинка  - Картинка
//     * Действие  - Строка
//     * ИзменяетСохраняемыеДанные - Булево
//
Функция СвойстваКоманды(Заголовок, Подсказка, Картинка = "", Действие = "", ИзменяетСохраняемыеДанные = Ложь) Экспорт
	
	Свойства = Новый Структура;
	Свойства.Вставить("Заголовок", Заголовок);
	Свойства.Вставить("Подсказка", Подсказка);
	Свойства.Вставить("Картинка",  ?(Картинка="", Новый Картинка(), Картинка)); 
	Свойства.Вставить("Действие",  Действие);
	Свойства.Вставить("ИзменяетСохраняемыеДанные", ИзменяетСохраняемыеДанные);
	
	Возврат Свойства;
	
КонецФункции

#КонецОбласти

#Область СлужебныйПрограммныйИнтерфейс

// Устанавливает доступность элементов контактной информации на форме.
//
// Параметры:
//    Форма - ФормаКлиентскогоПриложения - передаваемая форма.
//    Элементы - Соответствие из КлючИЗначение - список видов контактной информации, для которых устанавливается доступ:
//        * Ключ     - ОбъектМетаданных - подсистема, в которой размещается отчет или вариант отчета;
//        * Значение - Булево           - если ЛОЖЬ, то элемент доступен только для просмотра.
//    ИмяЭлементаДляРазмещения - Строка - имя группы, где размещена контактная информация.
//
Процедура УстановитьДоступностьЭлементовКонтактнойИнформации(Форма, Элементы, ИмяЭлементаДляРазмещения = "ГруппаКонтактнаяИнформация") Экспорт
	Для каждого Элемент Из Элементы Цикл
		
		Отбор = Новый Структура("Вид", Элемент.Ключ);
		НайденныеСтроки = УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеКонтактнойИнформацииНаФорме(Форма).НайтиСтроки(Отбор);
		Если НайденныеСтроки <> Неопределено Тогда
			Для Каждого НайденнаяСтрока Из НайденныеСтроки Цикл
				ЭлементКИ = Форма.Элементы[НайденнаяСтрока.ИмяРеквизита];
				ЭлементКИ.ТолькоПросмотр = НЕ Элемент.Значение;
			КонецЦикла;
			// Если у элемента только просмотр, то удаляем возможность добавления этого элемента на форму.
			ПараметрыКонтактнойИнформации = ПараметрыКонтактнойИнформацииФормы(Форма.ПараметрыКонтактнойИнформации, ИмяЭлементаДляРазмещения);
			Если НЕ Элемент.Значение Тогда
				Для Позиция = -ПараметрыКонтактнойИнформации.СписокДобавляемыхЭлементов.Количество() + 1 По 0 Цикл
					ЭлементКонтекстногоМеню = ПараметрыКонтактнойИнформации.СписокДобавляемыхЭлементов.Получить(-Позиция);
					Значение = ЭлементКонтекстногоМеню.Значение; // СправочникСсылка.ВидыКонтактнойИнформации 
					Если Значение.Ссылка = Элемент.Ключ Тогда
						ПараметрыКонтактнойИнформации.СписокДобавляемыхЭлементов.Удалить(-Позиция);
						Продолжить;
					КонецЕсли;
				КонецЦикла;
			КонецЕсли;
		КонецЕсли;
		
	КонецЦикла;
	
	Если Форма.Элементы.Найти("КонтактнаяИнформацияДобавитьПолеВвода") <> Неопределено Тогда
		ПараметрыКонтактнойИнформации = ПараметрыКонтактнойИнформацииФормы(Форма.ПараметрыКонтактнойИнформации, ИмяЭлементаДляРазмещения);
		Если ПараметрыКонтактнойИнформации.СписокДобавляемыхЭлементов.Количество() = 0 Тогда
			// Делаем кнопку Добавить недоступной, т.к. контекстное меню пустое. 
			КонтактнаяИнформацияДобавитьПолеВвода = Форма.Элементы.КонтактнаяИнформацияДобавитьПолеВвода; // ГруппаФормы
			КонтактнаяИнформацияДобавитьПолеВвода.Доступность = Ложь;
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

// Дополняет список колонки для загрузки данных колонками контактной информации.
//
// Параметры:
//  МетаданныеСправочника  - ОбъектМетаданных - метаданные справочника.
//  ИнформацияПоКолонкам   - ТаблицаЗначений - колонки макета.
//
Процедура КолонкиДляЗагрузкиДанных(МетаданныеСправочника, ИнформацияПоКолонкам) Экспорт
	
	Если МетаданныеСправочника.ТабличныеЧасти.Найти("КонтактнаяИнформация") = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Позиция = ИнформацияПоКолонкам.Количество() + 1;
	
	ВидыКонтактнойИнформации = ВидыКонтактнойИнформацииОбъекта(Справочники[МетаданныеСправочника.Имя].ПустаяСсылка());
	
	Для каждого ВидКонтактнойИнформации Из ВидыКонтактнойИнформации Цикл
		ИмяКолонки = "КонтактнаяИнформация_" + СтандартныеПодсистемыСервер.ПреобразоватьСтрокуВДопустимоеНаименованиеКолонки(ВидКонтактнойИнформации.Наименование);
		Если ИнформацияПоКолонкам.Найти(ИмяКолонки, "ИмяКолонки") = Неопределено Тогда
			СтрокаИнфоПроКолонки = ИнформацияПоКолонкам.Добавить();
			СтрокаИнфоПроКолонки.ИмяКолонки = ИмяКолонки;
			СтрокаИнфоПроКолонки.ПредставлениеКолонки = ВидКонтактнойИнформации.Представление;
			СтрокаИнфоПроКолонки.ТипКолонки = Новый ОписаниеТипов("Строка");
			СтрокаИнфоПроКолонки.ОбязательнаДляЗаполнения = Ложь;
			СтрокаИнфоПроКолонки.Позиция = Позиция;
			СтрокаИнфоПроКолонки.Группа = НСтр("ru = 'Контактная информация'");
			СтрокаИнфоПроКолонки.Видимость = Истина;
			СтрокаИнфоПроКолонки.Ширина = 30;
			Позиция = Позиция + 1;
		КонецЕсли;
	КонецЦикла;
	
КонецПроцедуры

// Возвращает тип контактной информации.
//
// Параметры:
//    Наименование - Строка - тип контактной информация в виде строки.
//
// Возвращаемое значение:
//    ПеречислениеСсылка.ТипыКонтактнойИнформации - соответствующий тип.
//
Функция ТипКонтактнойИнформацииПоНаименованию(Знач Наименование) Экспорт
	Возврат Перечисления.ТипыКонтактнойИнформации[Наименование];
КонецФункции

Процедура ПриСкрытииЗначенияРеквизита(ПолноеИмя, Значение, СтандартнаяОбработка) Экспорт
	
	ИмяТабличнойЧасти = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(".%1.", "КонтактнаяИнформация");
	Если СтрНайти(ПолноеИмя, ИмяТабличнойЧасти) = 0 Тогда
		Возврат;
	КонецЕсли;
	
	Если СтрЗаканчиваетсяНа(ПолноеИмя, "КонтактнаяИнформация.ЗначенияПолей") И ЗначениеЗаполнено(Значение) Тогда
	
		СтандартнаяОбработка = Ложь;
		Шаблон = "<КонтактнаяИнформация xmlns=""http://www.v8.1c.ru/ssl/contactinfo"" xmlns:xs=""http://www.w3.org/2001/XMLSchema"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" Представление=""%Представление%""></КонтактнаяИнформация>";
		Значение = СтрЗаменить(Шаблон, "%Представление%", Новый УникальныйИдентификатор);
	
	ИначеЕсли СтрЗаканчиваетсяНа(ПолноеИмя, "КонтактнаяИнформация.Значение") И ЗначениеЗаполнено(Значение) Тогда
		
		ПоляКонтактнойИнформации = УправлениеКонтактнойИнформациейСлужебный.СтрокуJSONВСтруктуру(Значение);
		
		Если ПоляКонтактнойИнформации.Количество() > 0 Тогда
		
			Для Каждого ПолеКонтактнойИнформации Из ПоляКонтактнойИнформации Цикл
				
				Если Не ЗначениеЗаполнено(ПолеКонтактнойИнформации.Значение)
					Или ТипЗнч(ПолеКонтактнойИнформации.Значение) = Тип("Массив")
					Или ПолеКонтактнойИнформации.Ключ = "type" Тогда
					Продолжить;
				КонецЕсли;
				
				ПоляКонтактнойИнформации[ПолеКонтактнойИнформации.Ключ] =
					СтрЗаменить(Строка(Новый УникальныйИдентификатор), "-", "");
					
			КонецЦикла;
			
			Значение = УправлениеКонтактнойИнформациейСлужебный.СтруктураВСтрокуJSON(ПоляКонтактнойИнформации);
		Иначе
			Значение = СтрЗаменить(Строка(Новый УникальныйИдентификатор), "-", "");
		КонецЕсли;
		
		СтандартнаяОбработка = Ложь;
		
	ИначеЕсли ЗначениеЗаполнено(Значение) Тогда
		
		Значение = СтрЗаменить(Строка(Новый УникальныйИдентификатор), "-", "");
		СтандартнаяОбработка = Ложь;
		
	КонецЕсли;
	
КонецПроцедуры

Функция АдресЭлектроннойПочты(Знач ЗначениеКонтактнойИнформации) Экспорт
	
	КонтактнаяИнформацияВФорматеJSON = КонтактнаяИнформацияВJSON(ЗначениеКонтактнойИнформации, Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты);
	
	КонтактнаяИнформацияСтруктурой = УправлениеКонтактнойИнформациейСлужебный.JSONВКонтактнуюИнформациюПоПолям(
		КонтактнаяИнформацияВФорматеJSON, Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты);
		
	Возврат КонтактнаяИнформацияСтруктурой.value;
	
КонецФункции

Функция НовыйАдресПочтыДляВосстановленияПароля(Знач СсылкаНаОбъект, Знач АдресЭлектроннойПочты) Экспорт
	
	Результат = Неопределено;
	
	Если СодержитКонтактнуюИнформацию(СсылкаНаОбъект) Тогда
		ПочтаОбъекта = КонтактнаяИнформацияОбъекта(СсылкаНаОбъект, 
			Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты, ТекущаяДатаСеанса(), Ложь);
		Если ПочтаОбъекта.Количество() > 0 Тогда
			Почта = ПочтаОбъекта.Найти(АдресЭлектроннойПочты, "Представление");
			Если Почта = Неопределено Тогда
				Результат = ПочтаОбъекта[0].Представление;
			КонецЕсли;
		Иначе
			Результат = "";
		КонецЕсли;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Параметры:
//  Форма - ФормаКлиентскогоПриложения
//  АдресЭлектроннойПочты - Строка
//  ДоступноРедактирование - Булево
//  ЭтоВнешнийПользователь - Булево
// Возвращаемое значение:
//   Строка
// 
Функция ОпределитьЭлементСПочтойДляВосстановленияПароля(Форма, АдресЭлектроннойПочты, ДоступноРедактирование, ЭтоВнешнийПользователь = Ложь) Экспорт
	
	Если ЭтоВнешнийПользователь Тогда
		ТипИлиВидEmailПользователя = Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты;
	Иначе
		ТипИлиВидEmailПользователя                = ВидКонтактнойИнформацииПоИмени("EmailПользователя");
	КонецЕсли;
	
	ИмяРеквизита = ИмяРеквизитыДляВосстановленияПароля(Форма, АдресЭлектроннойПочты, ТипИлиВидEmailПользователя);
	
	Если ЗначениеЗаполнено(ИмяРеквизита)
		И Форма.Элементы.Найти(ИмяРеквизита) <> Неопределено Тогда
		Форма.Элементы[ИмяРеквизита].Родитель.Подсказка = НСтр("ru = 'Используется для восстановления пароля.'");
		Форма.Элементы[ИмяРеквизита].Родитель.ОтображениеПодсказки = ОтображениеПодсказки.ОтображатьСправа;
		Форма.Элементы[ИмяРеквизита].Родитель.Доступность = ДоступноРедактирование;
	КонецЕсли;
	
	Возврат ИмяРеквизита;
	
КонецФункции

// Восстановление пароля

Функция СтрокаОписанияПочтыДляВосстановленияПароляИзДанныхФормы(Форма, ТипИлиВидEmailПользователя, АдресЭлектроннойПочты = "") Экспорт
	
	КонтактнаяИнформация = УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеКонтактнойИнформацииНаФорме(Форма);
	
	Отбор = Новый Структура;
	Если ТипЗнч(ТипИлиВидEmailПользователя) = Тип("СправочникСсылка.ВидыКонтактнойИнформации") Тогда
		Отбор.Вставить("Вид",           ТипИлиВидEmailПользователя);
	ИначеЕсли ТипЗнч(ТипИлиВидEmailПользователя) = Тип("ПеречислениеСсылка.ТипыКонтактнойИнформации") Тогда
		Отбор.Вставить("Тип",           ТипИлиВидEmailПользователя);
	КонецЕсли;
	
	Если ЗначениеЗаполнено(АдресЭлектроннойПочты) Тогда
		Отбор.Вставить("Представление", АдресЭлектроннойПочты);
	КонецЕсли;
	
	НайденныеСтроки = КонтактнаяИнформация.НайтиСтроки(Отбор);
	Если НайденныеСтроки.Количество() > 0 Тогда
		Возврат НайденныеСтроки[0];
	КонецЕсли;
	
	Возврат Неопределено;
	
КонецФункции

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

////////////////////////////////////////////////////////////////////////////////
// Инициализация элементов на форме объект-владельца контактной информации.

Процедура ОпределитьПараметрыКонтактнойИнформацииПоВладельцу(Форма, Объект, ПараметрыКонтактнойИнформации, ЭтоПараметрыОсновногоОбъекта, СкрываемыеВиды)
	
	СкрываемыеВиды = Новый Массив;
	Для каждого ПараметрКонтактнойИнформации Из Форма.ПараметрыКонтактнойИнформации Цикл
		
		Если ПараметрКонтактнойИнформации.Значение.Владелец = Объект.Ссылка
			Или Форма.ПараметрыКонтактнойИнформации.Количество() = 1 Тогда
				
				ПараметрыКонтактнойИнформации = ПараметрКонтактнойИнформации.Значение;
				СкрываемыеВиды = ПараметрыКонтактнойИнформации.СкрываемыеВиды;
				Возврат;
		КонецЕсли;
		
		ЭтоПараметрыОсновногоОбъекта = Ложь;
		
	КонецЦикла;

КонецПроцедуры

// Параметры:
//   Форма - ФормаКлиентскогоПриложения
//   ДобавляемыеРеквизиты - Массив из РеквизитФормы
//   ИмяОбъекта - Строка
//   РазмещеныНаФорме - Соответствие из КлючИЗначение:
//     * Ключ - СправочникСсылка.ВидыКонтактнойИнформации
//     * Значение - Булево
//   КонтактнаяИнформация - КоллекцияСтрокДереваЗначений:
//    * Вид              - СправочникСсылка.ВидыКонтактнойИнформации   - вид контактной информации.
//    * ИмяПредопределенногоВида - Строка
//    * ИмяПредопределенныхДанных - Строка
//    * Тип              - ПеречислениеСсылка.ТипыКонтактнойИнформации - тип контактной информации.
//    * ОбязательноеЗаполнение - Булево
//    * ВидПоляДругое - Строка
//    * РазрешитьВводНесколькихЗначений - Булево
//    * Наименование - Строка
//    * ХранитьИсториюИзменений - Булево
//    * ВидРедактирования - Строка
//    * ЭтоРеквизитТабличнойЧасти - Булево
//    * РеквизитДопУпорядочивания - Булево
//    * МеждународныйФорматАдреса - Булево
//    * ВводитьНомерПоМаске - Булево
//    * ЭтоИсторическаяКонтактнаяИнформация - Булево
//    * Представление    - Строка - представление контактной информации.
//    * ЗначенияПолей    - Строка - устаревший XML, соответствующий XDTO пакетам КонтактнаяИнформация или Адрес. Для
//                                  обратной совместимости.
//    * Значение    - Строка.
//    * ДействуетС    - Дата.
//    * НомерСтроки    - Число.
//    * ИдентификаторСтрокиТабличнойЧасти    - Число.
//    * ИмяРеквизита    - Строка.
//    * ПометкаУдаления    - Булево.
//    * Комментарий    - Строка.
//   ОтложеннаяИнициализация - Булево
//                           - Массив
//   ОбработкаНавигационнойСсылки - Булево
//
Процедура СоздатьРеквизитыКонтактнойИнформации(Знач Форма, Знач ДобавляемыеРеквизиты, Знач ИмяОбъекта, Знач РазмещеныНаФорме,
	Знач КонтактнаяИнформация, Знач ОтложеннаяИнициализация, Знач ОбработкаНавигационнойСсылки)
	
	Строка1500            = Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(1500));
	ФорматированнаяСтрока = Новый ОписаниеТипов("ФорматированнаяСтрока");
	
	СозданныеРеквизиты = ОбщегоНазначения.СкопироватьРекурсивно(РазмещеныНаФорме);
	ПредыдущийВид      = Неопределено;
	ПорядковыйНомер    = 1;
	
	Для Каждого ОбъектКонтактнойИнформации Из КонтактнаяИнформация Цикл
		
		Если ОбъектКонтактнойИнформации.ПометкаУдаления И ПустаяСтрока(ОбъектКонтактнойИнформации.Значение) Тогда
			Продолжить;
		КонецЕсли;
			
		Если ОбъектКонтактнойИнформации.ЭтоРеквизитТабличнойЧасти Тогда
			
			ИмяВидаКИ = ОбъектКонтактнойИнформации.ИмяПредопределенногоВида;
			Позиция = СтрНайти(ИмяВидаКИ, ИмяОбъекта);
			ИмяТабличнойЧасти = Сред(ИмяВидаКИ, Позиция + СтрДлина(ИмяОбъекта));
			
			ПредыдущийВид = Неопределено;
			ИмяРеквизита = "";
			
			ОбъектКонтактнойИнформации.Строки.Сортировать("РеквизитДопУпорядочивания");
			
			Для Каждого СтрокаКИ Из ОбъектКонтактнойИнформации.Строки Цикл
				
				ТекущийВид = СтрокаКИ.Вид;
				Если ТекущийВид <> ПредыдущийВид Тогда
					
					ИмяРеквизита = "КонтактнаяИнформацияПоле" + ИмяТабличнойЧасти + СтрЗаменить(ТекущийВид.УникальныйИдентификатор(), "-", "x")
						+ ОбъектКонтактнойИнформации.Строки.Индекс(СтрокаКИ);
					ПутьРеквизитов = "Объект." + ИмяТабличнойЧасти;
					
					ДобавляемыеРеквизиты.Добавить(Новый РеквизитФормы(ИмяРеквизита, Строка1500, ПутьРеквизитов, СтрокаКИ.Наименование, Истина));
					ДобавляемыеРеквизиты.Добавить(Новый РеквизитФормы(ИмяРеквизита + "Значение", Новый ОписаниеТипов("Строка"), ПутьРеквизитов,, Истина));
					ПредыдущийВид = ТекущийВид;
					
				КонецЕсли;
				
				СтрокаКИ.ИмяРеквизита = ИмяРеквизита;
				
			КонецЦикла;
			
		Иначе
			
			Если ОбъектКонтактнойИнформации.ЭтоИсторическаяКонтактнаяИнформация Тогда
				СкорректироватьКонтактнуюИнформацию(Форма, ОбъектКонтактнойИнформации);
				Продолжить;
			КонецЕсли;
			
			ТекущийВид = ОбъектКонтактнойИнформации.Вид;
			
			СозданныйРеквизит = СозданныеРеквизиты.Получить(ТекущийВид);
			Если СозданныйРеквизит <> Неопределено Тогда
				СозданныйРеквизит = ТекущийВид;
			КонецЕсли;
			
			Если НЕ ОбъектКонтактнойИнформации.ОтображатьВсегда И ПустаяСтрока(ОбъектКонтактнойИнформации.Значение) И СозданныйРеквизит = Неопределено Тогда
				Продолжить;
			КонецЕсли;
			
			Если ТекущийВид <> ПредыдущийВид Тогда
				ПредыдущийВид = ТекущийВид;
				ПорядковыйНомер = 1;
			Иначе
				ПорядковыйНомер = ПорядковыйНомер + 1;
			КонецЕсли;
			
			ЕстьПолеКомментарий = ДляТипаКонтактнойИнформацииЕстьПолеКомментарий(ОбъектКонтактнойИнформации.Тип, ОбработкаНавигационнойСсылки);
			
			Если СозданныйРеквизит = Неопределено Тогда
				ОбъектКонтактнойИнформации.ИмяРеквизита = "КонтактнаяИнформацияПоле" + СтрЗаменить(ТекущийВид.УникальныйИдентификатор(), "-", "x")
					+ Формат(ПорядковыйНомер, "ЧГ=0");
				Если ЕстьПолеКомментарий Тогда
					ОбъектКонтактнойИнформации.ИмяРеквизитаКомментарий = "КомментарийКонтактнаяИнформацияПоле" + СтрЗаменить(
						ТекущийВид.УникальныйИдентификатор(), "-", "x") + Формат(ПорядковыйНомер, "ЧГ=0");
				КонецЕсли;
				Если Не ОтложеннаяИнициализация Тогда
					
					ТипРеквизита = Строка1500;
					Если ОбъектКонтактнойИнформации.Тип = Перечисления.ТипыКонтактнойИнформации.ВебСтраница И ОбработкаНавигационнойСсылки Тогда
						ТипРеквизита = ФорматированнаяСтрока;
					КонецЕсли;
					
					ДобавляемыеРеквизиты.Добавить(
						Новый РеквизитФормы(ОбъектКонтактнойИнформации.ИмяРеквизита, ТипРеквизита,, ОбъектКонтактнойИнформации.Наименование, Истина));
					Если ЕстьПолеКомментарий Тогда					
						ДобавляемыеРеквизиты.Добавить(
							Новый РеквизитФормы(ОбъектКонтактнойИнформации.ИмяРеквизитаКомментарий, ТипРеквизита,, ОбъектКонтактнойИнформации.Наименование, Истина));
					КонецЕсли;
				КонецЕсли;
			Иначе
				ОбъектКонтактнойИнформации.ИмяРеквизита = "КонтактнаяИнформацияПоле" + ОбъектКонтактнойИнформации.ИмяПредопределенногоВида;
				Если ЕстьПолеКомментарий Тогда
					ОбъектКонтактнойИнформации.ИмяРеквизитаКомментарий = "КомментарийКонтактнаяИнформацияПоле" + ОбъектКонтактнойИнформации.ИмяПредопределенногоВида;
				КонецЕсли;
				СозданныеРеквизиты.Удалить(СозданныйРеквизит);
			КонецЕсли;
			
			СкорректироватьКонтактнуюИнформацию(Форма, ОбъектКонтактнойИнформации);
		КонецЕсли;
	КонецЦикла;
	
	// Добавим новые реквизиты
	Если ДобавляемыеРеквизиты.Количество() > 0 Тогда
		Форма.ИзменитьРеквизиты(ДобавляемыеРеквизиты);
	КонецЕсли;

КонецПроцедуры

Процедура СкрытьКонтактнуюИнформацию(Знач Форма, Знач ДобавляемыеРеквизиты, ПараметрыВывода)
	
	Если ДобавляемыеРеквизиты.Количество() > 0 Тогда
		Форма.ИзменитьРеквизиты(ДобавляемыеРеквизиты);
	КонецЕсли;
	ДобавленныеРеквизиты = Новый Массив;
	Для Каждого ДобавляемыйРеквизит Из ДобавляемыеРеквизиты Цикл
		Если ПустаяСтрока(ДобавляемыйРеквизит.Путь) Тогда
			ДобавленныеРеквизиты.Добавить(ДобавляемыйРеквизит.Имя);
		КонецЕсли;
	КонецЦикла;
	
	ДополнительныеПараметры = ДополнительныеПараметрыВыводаКонтактнойИнформации(ПараметрыВывода.ОписаниеКоманд,
		ПараметрыВывода.ОтображатьИконки, ПараметрыВывода.РазмещеныНаФорме, ПараметрыВывода.РазрешитьДобавлениеПолей,
		ПараметрыВывода.ИсключаемыеВиды, ПараметрыВывода.СкрываемыеВиды);
		
	ДополнительныеПараметры.ПоложениеКнопкиДобавить = ПараметрыВывода.ПоложениеКнопкиДобавить;
	ДополнительныеПараметры.ШиринаПоляКомментарий = ПараметрыВывода.ШиринаПоляКомментарий;	
		
	ПараметрыКонтактнойИнформации = ПараметрыВыводаКонтактнойИнформации(Форма, ПараметрыВывода.ИмяЭлементаДляРазмещения,
		ПараметрыВывода.ПоложениеЗаголовкаКИ, ПараметрыВывода.ОтложеннаяИнициализация, ДополнительныеПараметры);
		
	ПараметрыКонтактнойИнформации.ДобавленныеРеквизиты = ДобавленныеРеквизиты;
	ПараметрыКонтактнойИнформации.Владелец             = ПараметрыВывода.СсылкаНаОбъект;
	
	Если Не ПустаяСтрока(ПараметрыВывода.ИмяЭлементаДляРазмещения) Тогда
		Форма.Элементы[ПараметрыВывода.ИмяЭлементаДляРазмещения].Видимость = Ложь;
	КонецЕсли;
	
КонецПроцедуры

Процедура ДобавитьКнопкуДополнительногоПоляКонтактнойИнформации(Знач Форма, Знач ИмяЭлементаДляРазмещения)
	
	ПараметрыКонтактнойИнформацииЭлемента = Форма.ПараметрыКонтактнойИнформации[ИмяЭлементаДляРазмещения]; // см. ПараметрыВыводаКонтактнойИнформации
	
	Описание = НСтр("ru = 'Добавить дополнительное поле контактной информации'");
	ГруппаКоманды             = Группа("ГруппаКонтактнаяИнформацияДобавитьПолеВвода" + ИмяЭлементаДляРазмещения, 
		Форма, Описание, ИмяЭлементаДляРазмещения, "ГруппаЗначенияКомандыКИ"+ИмяЭлементаДляРазмещения);
	ГруппаКоманды.Отображение = ОтображениеОбычнойГруппы.ОбычноеВыделение;
	Если ПараметрыКонтактнойИнформацииЭлемента.ПоложениеКнопкиДобавить = "Авто"
		Или ПараметрыКонтактнойИнформацииЭлемента.ПоложениеКнопкиДобавить = "Право" Тогда
		ГоризонтальноеПоложениеВГруппе = ГоризонтальноеПоложениеЭлемента.Право;
	Иначе
		ГоризонтальноеПоложениеВГруппе = ГоризонтальноеПоложениеЭлемента.Лево;
	КонецЕсли;
	ГруппаКоманды.ГоризонтальноеПоложениеВГруппе = ГоризонтальноеПоложениеВГруппе;
	
	ИмяКоманды          = "КонтактнаяИнформацияДобавитьПолеВвода" + ИмяЭлементаДляРазмещения;
	Команда             = Форма.Команды.Добавить(ИмяКоманды);
	Команда.Подсказка   = Описание;
	Команда.Отображение = ОтображениеКнопки.КартинкаИТекст;
	Если НЕ ОбщегоНазначения.ЭтоМобильныйКлиент() Тогда
		Команда.Картинка    = БиблиотекаКартинок.ВыпадающийСписок;
	КонецЕсли;
	Команда.Действие    = "Подключаемый_КонтактнаяИнформацияВыполнитьКоманду";
	
	ПараметрыКонтактнойИнформацииЭлемента.ДобавленныеЭлементы.Добавить(ИмяКоманды, 9, Истина);
	
	Кнопка             = Форма.Элементы.Добавить(ИмяКоманды,Тип("КнопкаФормы"), ГруппаКоманды);
	Кнопка.Доступность = НЕ Форма.Элементы[ИмяЭлементаДляРазмещения].ТолькоПросмотр;
	Кнопка.Заголовок   = "+ " + НСтр("ru = 'Телефон, адрес'");
	Команда.ИзменяетСохраняемыеДанные     = Истина;
	Кнопка.ИмяКоманды                     = ИмяКоманды;
	Кнопка.ГоризонтальноеПоложениеВГруппе = ГоризонтальноеПоложениеВГруппе;
	Кнопка.ПоложениеКартинки              = ПоложениеКартинкиКнопкиФормы.Право;
	ПараметрыКонтактнойИнформацииЭлемента.ДобавленныеЭлементы.Добавить(ИмяКоманды, 2, Ложь);
	
	Если НЕ ОбщегоНазначения.ЭтоМобильныйКлиент() И ПараметрыКонтактнойИнформацииЭлемента.ПоложениеКнопкиДобавить = "Авто" Тогда
		// Определение варианта отображения кнопки (Слева, с отступом, без отступа)
		// Обработка ситуации, когда на форме выводится одновременно динамическая и статическая контактная информация.
		ЭлементыГруппыДляРазмещения = Форма.Элементы[ИмяЭлементаДляРазмещения].ПодчиненныеЭлементы;
		КоличествоГруппВОсновной = ЭлементыГруппыДляРазмещения.Количество();
		ЭлементыГруппыЗначенияКИ = Форма.Элементы["ГруппаЗначенияКИ"+ИмяЭлементаДляРазмещения].ПодчиненныеЭлементы;
		КоличествоГрупп = ЭлементыГруппыЗначенияКИ.Количество();
		
		Если КоличествоГрупп = 0 И КоличествоГруппВОсновной = 1 Тогда
			ГруппаКоманды.ГоризонтальноеПоложениеВГруппе = ГоризонтальноеПоложениеЭлемента.Лево;
			Кнопка.ГоризонтальноеПоложениеВГруппе = ГоризонтальноеПоложениеЭлемента.Лево;
		Иначе
			Если КоличествоГрупп = 0 И КоличествоГруппВОсновной > 1 Тогда
				ПоследняяГруппа = ЭлементыГруппыДляРазмещения[КоличествоГруппВОсновной - 2];
			ИначеЕсли КоличествоГрупп > 0 Тогда
				ПоследняяГруппа = ЭлементыГруппыЗначенияКИ[КоличествоГрупп - 1];
			КонецЕсли;
			
			ЕстьСтатическиеКнопкаКИ = ЕстьКнопкаКонтактнойИнформации(ЭлементыГруппыДляРазмещения, Ложь);
			ЕстьДинамическаяКнопкаКИ = ЕстьКнопкаКонтактнойИнформации(ЭлементыГруппыЗначенияКИ, Ложь);
			
			Если ПоследняяГруппа <> Неопределено И ЕстьГиперссылка(ПоследняяГруппа) Тогда
				ГруппаКоманды.ГоризонтальноеПоложениеВГруппе = ГоризонтальноеПоложениеЭлемента.Лево;
				Кнопка.ГоризонтальноеПоложениеВГруппе = ГоризонтальноеПоложениеЭлемента.Лево;
			ИначеЕсли ПоследняяГруппа <> Неопределено И НЕ ЕстьКнопкаКонтактнойИнформации(ПоследняяГруппа, Истина)
				И (ЕстьСтатическиеКнопкаКИ ИЛИ ЕстьДинамическаяКнопкаКИ) Тогда
				Декорация = Форма.Элементы.Добавить("ОтступДобавить", Тип("ДекорацияФормы"), ГруппаКоманды);
				Декорация.Вид       = ВидДекорацииФормы.Картинка;
				Декорация.Ширина    = 3;
				Декорация.Заголовок = НСтр("ru='Отступ'");
				Декорация.Высота    = 1;		
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

Процедура ДобавитьПояснениеПоСбросуНастроекФормы(Знач Форма, Знач ИмяЭлементаДляРазмещения, Знач ОтложеннаяИнициализация)
	
	ГруппаДляРазмещения = Форма.Элементы[ИмяЭлементаДляРазмещения];
	// Если отложенная инициализация и на странице нет элементов, то платформа скрывает страницу,
	// поэтому надо создавать временный элемент, который при переходе на страницу удаляется.
	Если ОтложеннаяИнициализация
		И ГруппаДляРазмещения.Вид = ВидГруппыФормы.Страница 
		И Форма.Элементы.Найти("КонтактнаяИнформацияЗаглушка") = Неопределено Тогда
		
		ГруппаСтраниц = ГруппаДляРазмещения.Родитель; // ГруппаФормы
		ЗаголовокСтраницы = ?(ЗначениеЗаполнено(ГруппаДляРазмещения.Заголовок), ГруппаДляРазмещения.Заголовок, ГруппаДляРазмещения.Имя);
		ЗаголовокГруппыСтраниц = ?(ЗначениеЗаполнено(ГруппаСтраниц.Заголовок), ГруппаСтраниц.Заголовок, ГруппаСтраниц.Имя);
		
		ПредупреждениеОРазмещении = НСтр("ru = 'Для отображения контактной информации разместите группу ""%1"" не первым элементом (после любой другой группы) в группе ""%2"" (меню Еще - Изменить форму).'");
		ПредупреждениеОРазмещении = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ПредупреждениеОРазмещении,
		ЗаголовокСтраницы, ЗаголовокГруппыСтраниц);
		ТекстПодсказки = НСтр("ru = 'Также можно установить стандартные настройки формы:
		|   • в меню Еще выбрать пункт Изменить форму...;
		|   • в открывшейся форме ""Настройка формы"" в меню Еще выбрать пункт ""Установить стандартные настройки"".'");
		
		Декорация = Форма.Элементы.Добавить("КонтактнаяИнформацияЗаглушка", Тип("ДекорацияФормы"), ГруппаДляРазмещения);
		Декорация.Заголовок              = ПредупреждениеОРазмещении;
		Декорация.ОтображениеПодсказки   = ОтображениеПодсказки.Кнопка;
		Декорация.Подсказка              = ТекстПодсказки;
		Декорация.ЦветТекста             = ЦветаСтиля.ПоясняющийОшибкуТекст;
		Декорация.АвтоМаксимальнаяВысота = Ложь;
	КонецЕсли;

КонецПроцедуры

Функция ЗаголовокСлева(Знач ПоложениеЗаголовкаКИ = Неопределено)
	
	Если ЗначениеЗаполнено(ПоложениеЗаголовкаКИ) Тогда
		ПоложениеЗаголовкаКИ = ПредопределенноеЗначение(ПоложениеЗаголовкаКИ);
	Иначе
		ПоложениеЗаголовкаКИ = ПоложениеЗаголовкаЭлементаФормы.Лево;
	КонецЕсли;
	
	Возврат (ПоложениеЗаголовкаКИ = ПоложениеЗаголовкаЭлементаФормы.Лево);
	
КонецФункции

Процедура ИзменитьКомментарий(Форма, ИмяРеквизита, ИмяЭлементаДляРазмещения, ТипКонтактнойИнформации)
	
	ОписаниеКонтактнойИнформации = УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеКонтактнойИнформацииНаФорме(Форма);
	
	Отбор = Новый Структура("ИмяРеквизита", ИмяРеквизита);
	НайденнаяСтрока = ОписаниеКонтактнойИнформации.НайтиСтроки(Отбор)[0];
	
	Если УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВJSON(НайденнаяСтрока.Значение) Тогда
		КонтактнаяИнформацияПоПолям = УправлениеКонтактнойИнформациейСлужебный.JSONВКонтактнуюИнформациюПоПолям(
			НайденнаяСтрока.Значение, Неопределено);
		КонтактнаяИнформацияПоПолям.Comment = НайденнаяСтрока.Комментарий;
		НайденнаяСтрока.Значение = УправлениеКонтактнойИнформациейСлужебный.СтруктураВСтрокуJSON(КонтактнаяИнформацияПоПолям);
	КонецЕсли;
	
	ПараметрыКИ = ПараметрыКонтактнойИнформацииФормы(Форма.ПараметрыКонтактнойИнформации, ИмяЭлементаДляРазмещения);
	ОбработкаНавигационнойСсылки = ПараметрыКИ.ОбработкаНавигационнойСсылки;
	Если НЕ ДляТипаКонтактнойИнформацииЕстьПолеКомментарий(ТипКонтактнойИнформации, ОбработкаНавигационнойСсылки) Тогда
		ПолеВвода = Форма.Элементы.Найти(ИмяРеквизита); // ДополнениеЭлементаФормы
		Если ТипКонтактнойИнформации = Перечисления.ТипыКонтактнойИнформации.Адрес 
			И ТипЗнч(ПолеВвода.РасширеннаяПодсказка.Заголовок) = Тип("ФорматированнаяСтрока") Тогда	
			КомандыДляВывода = УправлениеКонтактнойИнформациейКлиентСервер.КомандыДляВыводаНаФорму(ПараметрыКИ,
				ТипКонтактнойИнформации, НайденнаяСтрока.Вид, НайденнаяСтрока.ХранитьИсториюИзменений);
			ПолеВвода.РасширеннаяПодсказка.Заголовок = УправлениеКонтактнойИнформациейКлиентСервер.РасширеннаяПодсказкаАдреса(
				КомандыДляВывода, НайденнаяСтрока.Представление, НайденнаяСтрока.Комментарий);
		Иначе
			ПолеВвода.РасширеннаяПодсказка.Заголовок = НайденнаяСтрока.Комментарий;
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

Процедура ДобавитьСтрокуКонтактнойИнформации(Форма, Результат, ИмяЭлементаДляРазмещения, ЭтоНовыйВидКИ = Ложь, КоличествоАдресов = Неопределено, СледующаяСтрока = Неопределено)
	
	ДобавлениеНовогоЗначения = ТипЗнч(Результат) = Тип("Структура");
	
	Если ДобавлениеНовогоЗначения Тогда
		Результат.Свойство("ИмяЭлементаДляРазмещения", ИмяЭлементаДляРазмещения);
		
		ДобавляемыйВид = Результат.ДобавляемыйВид;
		Если ТипЗнч(ДобавляемыйВид)= Тип("СправочникСсылка.ВидыКонтактнойИнформации") Тогда
			ИнформацияОВидеКИ = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ДобавляемыйВид, "Тип, Наименование, ВидРедактирования, ВидПоляДругое, ВводитьНомерПоМаске, МаскаНомераТелефона");
		Иначе
			ИнформацияОВидеКИ = ДобавляемыйВид;
			ДобавляемыйВид    = ДобавляемыйВид.Ссылка;
		КонецЕсли;
	Иначе
		ИнформацияОВидеКИ = Результат;
		ДобавляемыйВид    = Результат.Вид;
	КонецЕсли;
	
	ТаблицаКонтактнойИнформации = УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеКонтактнойИнформацииНаФорме(Форма);
	ОтборПоВиду = Новый Структура("Вид, ЭтоИсторическаяКонтактнаяИнформация", ДобавляемыйВид, Ложь);
	
	ПараметрыКонтактнойИнформации = ПараметрыКонтактнойИнформацииФормы(Форма.ПараметрыКонтактнойИнформации, ИмяЭлементаДляРазмещения);
	ОбработкаНавигационнойСсылки = ПараметрыКонтактнойИнформации.ОбработкаНавигационнойСсылки;
	ЕстьПолеКомментарий = ДляТипаКонтактнойИнформацииЕстьПолеКомментарий(ИнформацияОВидеКИ.Тип, ОбработкаНавигационнойСсылки);
		
	Если ДобавлениеНовогоЗначения Тогда
		
		НайденныеСтроки = ТаблицаКонтактнойИнформации.НайтиСтроки(ОтборПоВиду);
		
		КоличествоСтрокВида = НайденныеСтроки.Количество();
		Если КоличествоСтрокВида > 0 Тогда
			ПоследняяСтрока = НайденныеСтроки.Получить(КоличествоСтрокВида - 1);
			ИндексДобавляемойСтроки = ТаблицаКонтактнойИнформации.Индекс(ПоследняяСтрока) + 1;
		Иначе
			ИндексДобавляемойСтроки = ТаблицаКонтактнойИнформации.Количество();
		КонецЕсли;
		
		ЭтоПоследняяСтрока = Ложь;
		Если ИндексДобавляемойСтроки = ТаблицаКонтактнойИнформации.Количество() Тогда
			ЭтоПоследняяСтрока = Истина;
		КонецЕсли;
		
		НоваяСтрока  = ТаблицаКонтактнойИнформации.Вставить(ИндексДобавляемойСтроки);
		ИмяРеквизита = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку("%1%2%3",
			"КонтактнаяИнформацияПоле",
			СтрЗаменить(ДобавляемыйВид.УникальныйИдентификатор(), "-", "x"),
			Формат(КоличествоСтрокВида + 1, "ЧГ=0"));
		ИмяРеквизитаКомментарий = "";
		Если ЕстьПолеКомментарий Тогда
			ИмяРеквизитаКомментарий = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку("%1%2%3%4",
			"Комментарий", "КонтактнаяИнформацияПоле",
			СтрЗаменить(ДобавляемыйВид.УникальныйИдентификатор(), "-", "x"),
			Формат(КоличествоСтрокВида + 1, "ЧГ=0"));
		КонецЕсли;
		НоваяСтрока.ИмяРеквизита              = ИмяРеквизита;
		НоваяСтрока.ИмяРеквизитаКомментарий   = ИмяРеквизитаКомментарий;
		НоваяСтрока.Вид                       = ДобавляемыйВид;
		НоваяСтрока.Тип                       = ИнформацияОВидеКИ.Тип;
		НоваяСтрока.ИмяЭлементаДляРазмещения  = ИмяЭлементаДляРазмещения;
		НоваяСтрока.ЭтоРеквизитТабличнойЧасти = Ложь;		
		
		Если ОбработкаНавигационнойСсылки = Истина И ИнформацияОВидеКИ.Тип = Перечисления.ТипыКонтактнойИнформации.ВебСтраница Тогда
			ОписаниеТипаРеквизита = Новый ОписаниеТипов("ФорматированнаяСтрока");
		Иначе
			ОписаниеТипаРеквизита = Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(500));
		КонецЕсли;
		
		МассивДобавляемыхРеквизитов = Новый Массив;
		МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы(ИмяРеквизита, ОписаниеТипаРеквизита,, ИнформацияОВидеКИ.Наименование, Истина));
		Если ЕстьПолеКомментарий Тогда
			МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы(ИмяРеквизитаКомментарий, ОписаниеТипаРеквизита,, ИнформацияОВидеКИ.Наименование, Истина));
		КонецЕсли;
		Форма.ИзменитьРеквизиты(МассивДобавляемыхРеквизитов);
		
		ЕстьКомментарий = Ложь;
		ОбязательноеЗаполнение = Ложь;
	Иначе
		ЭтоПоследняяСтрока = СледующаяСтрока = Неопределено;
		ИмяРеквизита = ИнформацияОВидеКИ.ИмяРеквизита;
		ИмяРеквизитаКомментарий = ИнформацияОВидеКИ.ИмяРеквизитаКомментарий;
		ЕстьКомментарий = ЗначениеЗаполнено(ИнформацияОВидеКИ.Комментарий);
		ОбязательноеЗаполнение = ИнформацияОВидеКИ.ОбязательноеЗаполнение;
	КонецЕсли;
	
	ДобавляемыйВидНаименование = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ДобавляемыйВид, "Наименование");
	
	// Отрисовка на форме
	Если ОбщегоНазначения.ЭтоМобильныйКлиент() И ПараметрыКонтактнойИнформации.ОтображатьИконки Тогда
		ГруппаСтрокиЗаголовок = Группа("ГруппаЗаголовок" + ИмяРеквизита, Форма, ДобавляемыйВидНаименование, ИмяЭлементаДляРазмещения, "ГруппаЗначенияКИ" + ИмяЭлементаДляРазмещения, 6);
		ГруппаСтрокиЗаголовок.Группировка = ГруппировкаПодчиненныхЭлементовФормы.Вертикальная;
		ГруппаСтрокиЗаголовок.Отображение = ОтображениеОбычнойГруппы.ОбычноеВыделение; 
		ГруппаСтрокиЗаголовокКартинка = Группа("ГруппаЗаголовокКартинка" + ИмяРеквизита, Форма, ДобавляемыйВидНаименование, ИмяЭлементаДляРазмещения, "ГруппаЗаголовок" + ИмяРеквизита);
		Декорация = Форма.Элементы.Добавить("Картинка" + ИмяРеквизита, Тип("ДекорацияФормы"), ГруппаСтрокиЗаголовокКартинка);
		Декорация.Заголовок = НСтр("ru='Картинка'");
		Декорация.Вид       = ВидДекорацииФормы.Картинка;
		Декорация.Ширина    = 2;
		Декорация.Картинка = КартинкаТипаКонтактнойИнформации(ИнформацияОВидеКИ.Тип);
		ПараметрыКонтактнойИнформации.ДобавленныеЭлементы.Добавить("Картинка" + ИмяРеквизита, 2, Ложь);
		ДекорацияЗаголовок = Форма.Элементы.Добавить("Заголовок" + ИмяРеквизита, Тип("ДекорацияФормы"), ГруппаСтрокиЗаголовокКартинка);
		ДекорацияЗаголовок.Заголовок = ВРег(ДобавляемыйВидНаименование);
		ДекорацияЗаголовок.Вид       = ВидДекорацииФормы.Надпись;
		ПараметрыКонтактнойИнформации.ДобавленныеЭлементы.Добавить("Заголовок" + ИмяРеквизита, 2, Ложь);
		ИмяГруппыРодителя = "ГруппаЗаголовок" + ИмяРеквизита;
	Иначе	 
		 ИмяГруппыРодителя = "ГруппаЗначенияКИ" + ИмяЭлементаДляРазмещения;
	КонецЕсли;
	
	ГруппаСтроки = Группа("Группа" + ИмяРеквизита, Форма, ДобавляемыйВидНаименование, ИмяЭлементаДляРазмещения, 
		ИмяГруппыРодителя);
	
	Если ОбщегоНазначения.ЭтоМобильныйКлиент() И НЕ ПараметрыКонтактнойИнформации.ОтображатьИконки Тогда
		ГруппаСтроки.ОтображатьЗаголовок = Истина;
	КонецЕсли;
	
	Родитель = Форма.Элементы["ГруппаЗначенияКИ" + ИмяЭлементаДляРазмещения];
	Если ОбщегоНазначения.ЭтоМобильныйКлиент() И ПараметрыКонтактнойИнформации.ОтображатьИконки Тогда
		
		Если Не ЭтоПоследняяСтрока И СледующаяСтрока = Неопределено Тогда
			ИмяСледующейГруппы = "ГруппаЗаголовок" + ПоследняяСтрока.ИмяРеквизита;
			Если Форма.Элементы.Найти(ИмяСледующейГруппы) <> Неопределено Тогда
				ИндексСледующейГруппы = Родитель.ПодчиненныеЭлементы.Индекс(Форма.Элементы[ИмяСледующейГруппы]) + 1;
				СледующаяГруппа = Родитель.ПодчиненныеЭлементы.Получить(ИндексСледующейГруппы);
				Форма.Элементы.Переместить(ГруппаСтрокиЗаголовок, Родитель, СледующаяГруппа);
			КонецЕсли;
		КонецЕсли;
		
	Иначе
		Если Не ЭтоПоследняяСтрока И СледующаяСтрока = Неопределено Тогда
			ИмяСледующейГруппы = "Группа" + ПоследняяСтрока.ИмяРеквизита;
			Если Форма.Элементы.Найти(ИмяСледующейГруппы) <> Неопределено Тогда
				ИндексСледующейГруппы = Родитель.ПодчиненныеЭлементы.Индекс(Форма.Элементы[ИмяСледующейГруппы]) + 1;
				СледующаяГруппа = Родитель.ПодчиненныеЭлементы.Получить(ИндексСледующейГруппы);
				Форма.Элементы.Переместить(ГруппаСтроки, Родитель, СледующаяГруппа);
			КонецЕсли;
		КонецЕсли;
		
	КонецЕсли;
		
	Если ОбщегоНазначения.ЭтоМобильныйКлиент() И ПараметрыКонтактнойИнформации.ОтображатьИконки Тогда
		ИмяСледующейГруппыТекущегоВида = "ГруппаЗаголовок" + ИмяРеквизита;
	Иначе
		ИмяСледующейГруппыТекущегоВида = "Группа" + ИмяРеквизита;
	КонецЕсли;
	
	// Обработка ситуации, когда на форме выводится одновременно множественная динамическая и статическая контактная информация.
	Если Форма.Элементы.Найти(ИмяСледующейГруппыТекущегоВида) <> Неопределено Тогда
		
		Отбор = Новый Структура("ИмяРеквизита", ИмяРеквизита);
		НайденныеСтрокиТекущегоВида = ТаблицаКонтактнойИнформации.НайтиСтроки(Отбор);
		Если НайденныеСтрокиТекущегоВида.Количество() > 0 Тогда
			ТекущийВид = НайденныеСтрокиТекущегоВида[0].Вид;
		КонецЕсли;
		
		ИндексПредыдущейГруппыВида = Родитель.ПодчиненныеЭлементы.Индекс(Форма.Элементы[ИмяСледующейГруппыТекущегоВида]) - 1;
		Если ИндексПредыдущейГруппыВида >= 0 Тогда
			ПредыдущаяГруппаВида = Родитель.ПодчиненныеЭлементы.Получить(ИндексПредыдущейГруппыВида);

			Если ПредыдущаяГруппаВида <> Неопределено Тогда

				Если ОбщегоНазначения.ЭтоМобильныйКлиент() И ПараметрыКонтактнойИнформации.ОтображатьИконки Тогда		
					Отбор = Новый Структура("ИмяРеквизита", СтрЗаменить(ПредыдущаяГруппаВида.Имя, "ГруппаЗаголовок", ""));
				Иначе
					Отбор = Новый Структура("ИмяРеквизита", СтрЗаменить(ПредыдущаяГруппаВида.Имя, "Группа", ""));
				КонецЕсли;
				НайденныеСтрокиПредыдущегоВида = ТаблицаКонтактнойИнформации.НайтиСтроки(Отбор);
				Если НайденныеСтрокиПредыдущегоВида.Количество() > 0 Тогда
					ПредыдущийВид = НайденныеСтрокиПредыдущегоВида[0].Вид;
				КонецЕсли;

				Если ТекущийВид <> ПредыдущийВид Тогда
					ЭтоНовыйВидКИ = Истина;
				КонецЕсли;
			КонецЕсли;
		Иначе
			ЭтоНовыйВидКИ = Истина;
		КонецЕсли;
	КонецЕсли;

	Если ПараметрыКонтактнойИнформации.ОтображатьИконки И НЕ ОбщегоНазначения.ЭтоМобильныйКлиент() Тогда
		ГруппаСтроки.Объединенная = Ложь;
		Декорация = Форма.Элементы.Добавить("Картинка" + ИмяРеквизита, Тип("ДекорацияФормы"), ГруппаСтроки);
		Декорация.Заголовок = НСтр("ru='Картинка'");
		Декорация.Вид       = ВидДекорацииФормы.Картинка;
		Декорация.Ширина    = 2;
		ПараметрыКонтактнойИнформации.ДобавленныеЭлементы.Добавить("Картинка" + ИмяРеквизита, 2, Ложь);
		Если ЭтоНовыйВидКИ Тогда
			Декорация.Картинка = КартинкаТипаКонтактнойИнформации(ИнформацияОВидеКИ.Тип);
		Иначе
			Декорация.Заголовок = НСтр("ru='Отступ'");
			Декорация.Высота    = 1;
		КонецЕсли;
	КонецЕсли;
	
	Если ЕстьПолеКомментарий Тогда
		ГруппаПолеКомментарий  = Группа("ГруппаКомментарий" + ИмяРеквизита, Форма,
			СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = '%1 поле, комментарий'"),
			ДобавляемыйВидНаименование), ИмяЭлементаДляРазмещения, "Группа" + ИмяРеквизита, 4);
	Иначе
		ГруппаПолеКомментарий = ГруппаСтроки;
	КонецЕсли;
	
	Если ПараметрыКонтактнойИнформации.ГруппаДляРазмещенияОграниченаШириной Тогда
		Форма.Элементы[ИмяЭлементаДляРазмещения].РастягиватьПоГоризонтали = Ложь;
	КонецЕсли;
	
	ПолеВвода = СоздатьПолеВвода(Форма, ГруппаПолеКомментарий, ИнформацияОВидеКИ, ИмяРеквизита, ИмяЭлементаДляРазмещения, ЭтоНовыйВидКИ, ОбязательноеЗаполнение);
	
	Если ОбщегоНазначения.ЭтоМобильныйКлиент() Тогда
		ПолеВвода.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Нет;
	КонецЕсли;
	
	Если ЕстьПолеКомментарий Тогда
		ПолеКомментарий = Форма.Элементы.Добавить(ИмяРеквизитаКомментарий, Тип("ПолеФормы"), ГруппаПолеКомментарий);
		ПолеКомментарий.Вид = ВидПоляФормы.ПолеВвода;
		ПолеКомментарий.Заголовок = НСтр("ru='Комментарий'");
		ПолеКомментарий.ПутьКДанным = ИмяРеквизитаКомментарий;
		ПолеКомментарий.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Нет;
		ПолеКомментарий.ПропускатьПриВводе = Истина;
		ПолеКомментарий.ПодсказкаВвода = НСтр("ru='Примечание'");
		ПолеКомментарий.АвтоМаксимальнаяШирина = Ложь;
		ШиринаПоляКомментарий = ?(ПараметрыКонтактнойИнформации.ГруппаДляРазмещенияОграниченаШириной, ПараметрыКонтактнойИнформации.ШиринаПоляКомментарий, 30);
		ПолеКомментарий.МаксимальнаяШирина = ШиринаПоляКомментарий;
		ПолеКомментарий.Ширина = ШиринаПоляКомментарий;
		ПолеКомментарий.РастягиватьПоГоризонтали = Ложь;
		ПолеКомментарий.РастягиватьПоВертикали = Ложь;
		ПолеКомментарий.УстановитьДействие("ПриИзменении", "Подключаемый_КонтактнаяИнформацияПриИзменении");
		ПараметрыКонтактнойИнформации.ДобавленныеЭлементы.Добавить(ИмяРеквизитаКомментарий, 2, Ложь);
		Если ОбщегоНазначения.ЭтоМобильныйКлиент() Тогда
			ПолеКомментарий.МногострочныйРежим = Истина;
		КонецЕсли;
	ИначеЕсли ЕстьКомментарий Тогда
		ПолеВвода.РасширеннаяПодсказка.Заголовок              = ИнформацияОВидеКИ.Комментарий;
		ПолеВвода.РасширеннаяПодсказка.АвтоМаксимальнаяШирина = Ложь;
		ПолеВвода.РасширеннаяПодсказка.МаксимальнаяШирина     = ПолеВвода.Ширина;
		ПолеВвода.РасширеннаяПодсказка.Ширина                 = ПолеВвода.Ширина;
	КонецЕсли;
	
	Если КоличествоАдресов = Неопределено Тогда
		ОтборПоТипу = Новый Структура("Тип", Перечисления.ТипыКонтактнойИнформации.Адрес);
		КоличествоАдресов = ТаблицаКонтактнойИнформации.НайтиСтроки(ОтборПоТипу).Количество();
	КонецЕсли;
	
	СоздатьДействие(Форма, ИнформацияОВидеКИ, ИмяРеквизита, ГруппаСтроки, ИмяЭлементаДляРазмещения);
	
	Если Не ЭтоНовыйВидКИ Тогда
		Если ТаблицаКонтактнойИнформации.Количество() > 1 И ТаблицаКонтактнойИнформации[0].Свойство("ЭтоИсторическаяКонтактнаяИнформация") Тогда
			ПунктКонтекстногоМенюПеремещения(ПолеВвода, Форма, 1, ИмяЭлементаДляРазмещения);
			НайденныеСтроки = ТаблицаКонтактнойИнформации.НайтиСтроки(ОтборПоВиду);
			Если НайденныеСтроки.Количество() > 1 Тогда
				ПредыдущаяСтрока = НайденныеСтроки.Получить(НайденныеСтроки.Количество() - 2);
				ПунктКонтекстногоМенюПеремещения(Форма.Элементы[ПредыдущаяСтрока.ИмяРеквизита], Форма, - 1, ИмяЭлементаДляРазмещения);
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	
	Если ДобавлениеНовогоЗначения Тогда
		Форма.ТекущийЭлемент = Форма.Элементы[ИмяРеквизита];
		Если ИнформацияОВидеКИ.Тип = Перечисления.ТипыКонтактнойИнформации.Адрес
			И ИнформацияОВидеКИ.ВидРедактирования = "Диалог" Тогда
			Результат.Вставить("ЭлементФормыАдреса", ИмяРеквизита);
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

Функция СоздатьПолеВвода(Форма, Родитель, ИнформацияОВидеКИ, ИмяРеквизита, ИмяЭлементаДляРазмещения,ЭтоНовыйВидКИ = Ложь, ОбязательноеЗаполнение = Ложь)
	
	ПараметрыКонтактнойИнформации = ПараметрыКонтактнойИнформацииФормы(Форма.ПараметрыКонтактнойИнформации, ИмяЭлементаДляРазмещения);
	ОбработкаНавигационнойСсылки = ПараметрыКонтактнойИнформации.ОбработкаНавигационнойСсылки;
	
	ЗаголовокСлева = ЗаголовокСлева(ПараметрыКонтактнойИнформации.ПоложениеЗаголовка);
	Элемент = Форма.Элементы.Добавить(ИмяРеквизита, Тип("ПолеФормы"), Родитель); // ПолеФормы, РасширениеПоляФормыДляПоляВвода, РасширениеПоляФормыДляПоляНадписи
	Элемент.ПутьКДанным = ИмяРеквизита;
	
	ГруппаДляРазмещенияОграниченаШириной = ПараметрыКонтактнойИнформации.ГруппаДляРазмещенияОграниченаШириной;
	
	Если ИнформацияОВидеКИ.ВидРедактирования = "Диалог" И ИнформацияОВидеКИ.Тип = Перечисления.ТипыКонтактнойИнформации.Адрес Тогда
		
			Элемент.Вид = ВидПоляФормы.ПолеНадписи;
			Элемент.Гиперссылка = Истина;
			Элемент.УстановитьДействие("Нажатие", "Подключаемый_КонтактнаяИнформацияПриНажатии");
			Если ПустаяСтрока(Форма[ИмяРеквизита]) Тогда
				Форма[ИмяРеквизита] = УправлениеКонтактнойИнформациейКлиентСервер.ТекстПустогоАдресаВВидеГиперссылки();
			КонецЕсли;
		
	ИначеЕсли ИнформацияОВидеКИ.Тип = Перечисления.ТипыКонтактнойИнформации.ВебСтраница И ОбработкаНавигационнойСсылки Тогда
		
		Элемент.Вид = ВидПоляФормы.ПолеНадписи;
		Элемент.УстановитьДействие("ОбработкаНавигационнойСсылки", "Подключаемый_КонтактнаяИнформацияОбработкаНавигационнойСсылки");
		
		Если ТипЗнч(ИнформацияОВидеКИ) <> Тип("Структура") И УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВJSON(ИнформацияОВидеКИ.Значение) Тогда
			КонтактнаяИнформация = УправлениеКонтактнойИнформациейСлужебный.JSONВКонтактнуюИнформациюПоПолям(ИнформацияОВидеКИ.Значение, Перечисления.ТипыКонтактнойИнформации.ВебСтраница);
			АдресСайта    = КонтактнаяИнформация.value;
			Представление = ?(КонтактнаяИнформация.Свойство("name") И ЗначениеЗаполнено(КонтактнаяИнформация.name), КонтактнаяИнформация.name, ИнформацияОВидеКИ.Представление);
		Иначе
			АдресСайта = "";
			Представление = УправлениеКонтактнойИнформациейКлиентСервер.ТекстПустогоАдресаВВидеГиперссылки();
		КонецЕсли;
		
		Форма[ИмяРеквизита] = УправлениеКонтактнойИнформациейКлиентСервер.АдресСайта(Представление, АдресСайта, Форма.ТолькоПросмотр);
		
	Иначе
		
		Элемент.Вид = ВидПоляФормы.ПолеВвода;
		Если ИнформацияОВидеКИ.ВидРедактирования = "Диалог" И ИнформацияОВидеКИ.Тип <> Перечисления.ТипыКонтактнойИнформации.ВебСтраница Тогда
			Элемент.РедактированиеТекста = Ложь;
		КонецЕсли;
		
		Элемент.УстановитьДействие("Очистка", "Подключаемый_КонтактнаяИнформацияОчистка");
		
		Если ИнформацияОВидеКИ.Тип = Перечисления.ТипыКонтактнойИнформации.Адрес Тогда
			Элемент.УстановитьДействие("Автоподбор",      "Подключаемый_КонтактнаяИнформацияАвтоподбор");
			Элемент.УстановитьДействие("ОбработкаВыбора", "Подключаемый_КонтактнаяИнформацияОбработкаВыбора");
		КонецЕсли;
		Если ОбщегоНазначения.ЭтоМобильныйКлиент() Тогда
			Элемент.МногострочныйРежим = Истина;
		КонецЕсли;
		
	КонецЕсли;
	
	Элемент.ОтображениеПодсказки = ОтображениеПодсказки.ОтображатьСнизу;
	Элемент.РастягиватьПоГоризонтали = Ложь;
	Элемент.РастягиватьПоВертикали = Ложь;
	
	Элемент.ВысотаЗаголовка = ?(ОбщегоНазначения.ЭтоМобильныйКлиент(), 1, 3);
	
	УстановитьСвойстваПолейВвода(ИнформацияОВидеКИ, Элемент, Форма, ИмяРеквизита, ОбработкаНавигационнойСсылки);
	
	Если Не ЭтоНовыйВидКИ Тогда
		Элемент.ГоризонтальноеПоложениеВГруппе = ГоризонтальноеПоложениеЭлемента.Право;
		Элемент.ЦветТекстаЗаголовка = ЦветаСтиля.ЦветФонаФормы;
	КонецЕсли;
	
	Элемент.ПоложениеЗаголовка = ?(ЗаголовокСлева, ПоложениеЗаголовкаЭлементаФормы.Лево, ПоложениеЗаголовкаЭлементаФормы.Верх);
	Если ЗаголовокСлева Тогда
		Элемент.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Лево;
	Иначе
		Элемент.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Верх;
	КонецЕсли;
	
	ПараметрыКонтактнойИнформации.ДобавленныеЭлементы.Добавить(ИмяРеквизита, 2, Ложь);
	
	Если ИнформацияОВидеКИ.Тип = Перечисления.ТипыКонтактнойИнформации.Адрес И Не ИнформацияОВидеКИ.ПометкаУдаления Тогда
		// Заполнить
		ГруппаПодменюАдреса = Форма.Элементы.Добавить("КонтекстноеПодменюКопироватьАдреса" + ИмяРеквизита, Тип(
			"ГруппаФормы"), Элемент.КонтекстноеМеню);
		ГруппаПодменюАдреса.Вид = ВидГруппыФормы.Подменю;
		ГруппаПодменюАдреса.Отображение = ОтображениеКнопки.Текст;
		ГруппаПодменюАдреса.Заголовок = НСтр("ru = 'Заполнить'");
	КонецЕсли;
	
	Если ОбязательноеЗаполнение И ЭтоНовыйВидКИ И Элемент.Вид = ВидПоляФормы.ПолеВвода Тогда
		Элемент.АвтоОтметкаНезаполненного = Истина;
	КонецЕсли;
	
	// Редактирование в диалоге
	Если ДляТипаКонтактнойИнформацииДоступноРедактированиеВДиалоге(ИнформацияОВидеКИ.Тип)
		И Элемент.Вид = ВидПоляФормы.ПолеВвода И ИнформацияОВидеКИ.ВидРедактирования <> "ПолеВвода" Тогда
		
		ДоступенВыбор = Не ИнформацияОВидеКИ.ПометкаУдаления И ИнформацияОВидеКИ.ВидРедактирования <> "ПолеВвода";
		
		Если ДоступенВыбор И Не Форма.ТолькоПросмотр Тогда
			Элемент.КнопкаВыбора = Истина;
			Элемент.УстановитьДействие("НачалоВыбора", "Подключаемый_КонтактнаяИнформацияНачалоВыбора");
		Иначе
			Элемент.КнопкаВыбора   = Ложь;
			Если ЗначениеЗаполнено(Форма[ИмяРеквизита]) Тогда
				Элемент.КнопкаОткрытия = Истина;
				Элемент.УстановитьДействие("Открытие", "Подключаемый_КонтактнаяИнформацияПриНажатии");
			КонецЕсли;
		КонецЕсли;
		
	КонецЕсли;
	
	Элемент.УстановитьДействие("ПриИзменении", "Подключаемый_КонтактнаяИнформацияПриИзменении");
	
	Если ИнформацияОВидеКИ.ПометкаУдаления Тогда
		
		Элемент.ШрифтЗаголовка = ШрифтыСтиля.ЗаголовокУдаленногоРеквизитаШрифт;
		Если Не ИнформацияОВидеКИ.ВидРедактирования = "Диалог" Тогда
			Элемент.КнопкаОчистки        = Истина;
			Элемент.РедактированиеТекста = Ложь;
			Элемент.Ширина = Элемент.Ширина - 2;
		Иначе
			Элемент.ТолькоПросмотр       = Истина;
		КонецЕсли;
		
	КонецЕсли;
	
	Если ГруппаДляРазмещенияОграниченаШириной Тогда
		Элемент.Ширина = 0;
		Элемент.МаксимальнаяШирина = 0;
		Элемент.АвтоМаксимальнаяШирина = Ложь;
		Элемент.РастягиватьПоГоризонтали = Истина
	КонецЕсли;
	
	Возврат Элемент;
	
КонецФункции

Процедура ПодготовитьСтатическийЭлемент(Форма, СтрокаКИ, СозданныеЭлементы, СозданныйЭлемент, ОтображатьИконки, ИмяЭлементаДляРазмещения)
	
	СозданныеЭлементы.Удалить(СозданныйЭлемент);
	
	Если Форма.ТолькоПросмотр Тогда
		ЭлементНаФорме = Форма.Элементы[СтрокаКИ.ИмяРеквизита];
		Если ЭлементНаФорме.Вид = ВидПоляФормы.ПолеВвода Тогда
			Если ДляТипаКонтактнойИнформацииДоступноРедактированиеВДиалоге(СтрокаКИ.Тип) Тогда
				ЭлементНаФорме.КнопкаВыбора = Ложь;
				Если ЗначениеЗаполнено(Форма[СтрокаКИ.ИмяРеквизита]) Тогда
					ЭлементНаФорме.КнопкаОткрытия = Истина;
					ЭлементНаФорме.УстановитьДействие("Открытие", "Подключаемый_КонтактнаяИнформацияПриНажатии");
				КонецЕсли;
			Иначе
				ЭлементНаФорме.ТолькоПросмотр = Истина;
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	
	УстановитьДействияДляСтатическихЭлементов(Форма, СтрокаКИ, ИмяЭлементаДляРазмещения);
	
	ИмяЭлементаГруппаСтроки = "Группа" + СтрокаКИ.ИмяРеквизита;
	Если Форма.Элементы.Найти(ИмяЭлементаГруппаСтроки) <> Неопределено Тогда
		ГруппаСтроки = Форма.Элементы[ИмяЭлементаГруппаСтроки];
		Если ГруппаСтроки.Родитель = Форма.Элементы[ИмяЭлементаДляРазмещения]
			ИЛИ ГруппаСтроки.Родитель = Форма.Элементы["ГруппаЗначенияКИ"+ИмяЭлементаДляРазмещения] Тогда			
			Форма.Элементы.Переместить(ГруппаСтроки, Форма.Элементы["ГруппаЗначенияКИ"+ИмяЭлементаДляРазмещения]);
		КонецЕсли;
		ПараметрыКонтактнойИнформации = ПараметрыКонтактнойИнформацииФормы(Форма.ПараметрыКонтактнойИнформации, ИмяЭлементаДляРазмещения);
		
		ИмяКнопки = "Команда" + СтрокаКИ.ИмяРеквизита;
		Если Форма.Элементы.Найти(ИмяКнопки) <> Неопределено Тогда
			Кнопка = Форма.Элементы[ИмяКнопки];
			Если Форма.Команды[Кнопка.ИмяКоманды].Действие = "Подключаемый_КонтактнаяИнформацияВыполнитьКоманду" Тогда
				ОтображатьИсторию = СтрокаКИ.ХранитьИсториюИзменений И Не СтрокаКИ.ПометкаУдаления;
				КомандыДляВывода = УправлениеКонтактнойИнформациейКлиентСервер.КомандыДляВыводаНаФорму(ПараметрыКонтактнойИнформации, 
					СтрокаКИ.Тип, СтрокаКИ.Вид, ОтображатьИсторию);
				КоличествоКоманд = КомандыДляВывода.Количество();
				Если КоличествоКоманд = 1 Тогда
					Для Каждого КомандаВывода Из КомандыДляВывода Цикл
						ЗаполнитьЗначенияСвойств(Кнопка, КомандаВывода.Значение, "Картинка");
					КонецЦикла;
				ИначеЕсли КоличествоКоманд > 1 Тогда
					Кнопка.Картинка = БиблиотекаКартинок.МенюДополнительныеФункции;
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;
		
		Если ОбщегоНазначения.ЭтоМобильныйКлиент() Тогда
			
			Если Форма.Элементы.Найти(СтрокаКИ.ИмяРеквизита) <> Неопределено Тогда
				ПолеВвода = Форма.Элементы[СтрокаКИ.ИмяРеквизита];
				ПолеВвода.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Нет;
				Если ПолеВвода.Вид = ВидПоляФормы.ПолеВвода Тогда
					ПолеВвода.МногострочныйРежим = Истина;
				КонецЕсли;
			КонецЕсли;
			
			Если ОтображатьИконки Тогда	
				ГруппаСтрокиЗаголовок = Группа("ГруппаЗаголовок" + СтрокаКИ.ИмяРеквизита, Форма, ГруппаСтроки.Заголовок, ИмяЭлементаДляРазмещения, "ГруппаЗначенияКИ"+ИмяЭлементаДляРазмещения, 6);
				ГруппаСтрокиЗаголовок.Группировка = ГруппировкаПодчиненныхЭлементовФормы.Вертикальная;
				ГруппаСтрокиЗаголовок.Отображение = ОтображениеОбычнойГруппы.ОбычноеВыделение; 
				
				ГруппаСтрокиЗаголовокКартинка = Группа("ГруппаЗаголовокКартинка" + СтрокаКИ.ИмяРеквизита, Форма, ГруппаСтроки.Заголовок, ИмяЭлементаДляРазмещения, "ГруппаЗаголовок" + СтрокаКИ.ИмяРеквизита);
				
								
				ИмяЭлементаКартинка = "Картинка" + СтрокаКИ.ИмяРеквизита;
				Если Форма.Элементы.Найти(ИмяЭлементаКартинка) <> Неопределено Тогда
					ЭлементКартинка = Форма.Элементы[ИмяЭлементаКартинка];			
					Форма.Элементы.Переместить(ЭлементКартинка, ГруппаСтрокиЗаголовокКартинка);			
				Иначе
					ЭлементКартинка = Форма.Элементы.Добавить(ИмяЭлементаКартинка, Тип("ДекорацияФормы"), ГруппаСтрокиЗаголовокКартинка);
					ЭлементКартинка.Заголовок = НСтр("ru='Картинка'");
					ЭлементКартинка.Вид       = ВидДекорацииФормы.Картинка;
					ЭлементКартинка.Ширина    = 2;
					ЭлементКартинка.Картинка = КартинкаТипаКонтактнойИнформации(СтрокаКИ.Тип);
					ПараметрыКонтактнойИнформации.ДобавленныеЭлементы.Добавить("Картинка" + СтрокаКИ.ИмяРеквизита, 2, Ложь);
				КонецЕсли;
				
				ИмяЭлементаЗаголовок = "Заголовок" + СтрокаКИ.ИмяРеквизита;
				Если Форма.Элементы.Найти(ИмяЭлементаЗаголовок) <> Неопределено Тогда
					ЭлементЗаголовок = Форма.Элементы[ИмяЭлементаЗаголовок];			
					Форма.Элементы.Переместить(ЭлементЗаголовок, ГруппаСтрокиЗаголовокКартинка);			
				Иначе
				ДекорацияЗаголовок = Форма.Элементы.Добавить(ИмяЭлементаЗаголовок, Тип("ДекорацияФормы"), ГруппаСтрокиЗаголовокКартинка);
				ДекорацияЗаголовок.Заголовок = ВРег(ГруппаСтроки.Заголовок);
				ДекорацияЗаголовок.Вид       = ВидДекорацииФормы.Надпись;			
				ПараметрыКонтактнойИнформации.ДобавленныеЭлементы.Добавить("Заголовок" + СтрокаКИ.ИмяРеквизита, 2, Ложь);
				КонецЕсли;
				
				Форма.Элементы.Переместить(ГруппаСтроки, ГруппаСтрокиЗаголовок);
				
			Иначе			
				ГруппаСтроки.ОтображатьЗаголовок = Истина;
			КонецЕсли;
			
		Иначе
			
			Если ПараметрыКонтактнойИнформации.ГруппаДляРазмещенияОграниченаШириной Тогда
				Если Форма.Элементы.Найти(СтрокаКИ.ИмяРеквизита) <> Неопределено Тогда
					ПолеВвода = Форма.Элементы[СтрокаКИ.ИмяРеквизита];
					ПолеВвода.Ширина = 0;
					ПолеВвода.МаксимальнаяШирина = 0;
					ПолеВвода.АвтоМаксимальнаяШирина = Ложь;
					ПолеВвода.РастягиватьПоГоризонтали = Истина;
				КонецЕсли;
				
				ИмяЭлементаКомментарий = "Комментарий" + СтрокаКИ.ИмяРеквизита;
				Если Форма.Элементы.Найти(ИмяЭлементаКомментарий) <> Неопределено Тогда
					ПолеКомментарий = Форма.Элементы[ИмяЭлементаКомментарий];
					ПолеКомментарий.МаксимальнаяШирина = ПараметрыКонтактнойИнформации.ШиринаПоляКомментарий;
					ПолеКомментарий.Ширина = ПараметрыКонтактнойИнформации.ШиринаПоляКомментарий;
				КонецЕсли; 
			Иначе
				Если Форма.Элементы.Найти(СтрокаКИ.ИмяРеквизита) <> Неопределено Тогда
					ПолеВвода = Форма.Элементы[СтрокаКИ.ИмяРеквизита]; 
					ОбработкаНавигационнойСсылки = ПараметрыКонтактнойИнформации.ОбработкаНавигационнойСсылки;
					УстановитьСвойстваПолейВвода(СтрокаКИ, ПолеВвода, Форма, СтрокаКИ.ИмяРеквизита, ОбработкаНавигационнойСсылки);
				КонецЕсли;
			КонецЕсли;
			
			ИмяЭлементаКартинка = "Картинка" + СтрокаКИ.ИмяРеквизита;
			Если ОтображатьИконки И Форма.Элементы.Найти(ИмяЭлементаКартинка) = Неопределено Тогда
				Если ГруппаСтроки.Родитель = Форма.Элементы["ГруппаЗначенияКИ"+ИмяЭлементаДляРазмещения] Тогда
					ГруппаСтроки.Объединенная = Ложь;
				КонецЕсли;
				Декорация = Форма.Элементы.Добавить(ИмяЭлементаКартинка, Тип("ДекорацияФормы"), ГруппаСтроки);
				Декорация.Заголовок = НСтр("ru='Картинка'");
				Декорация.Вид       = ВидДекорацииФормы.Картинка;
				Декорация.Ширина    = 2;
				Декорация.Картинка = КартинкаТипаКонтактнойИнформации(СтрокаКИ.Тип);
				Если Форма.Элементы.Найти(СтрокаКИ.ИмяРеквизита) <> Неопределено Тогда
					Форма.Элементы.Переместить(Декорация, ГруппаСтроки, Форма.Элементы[СтрокаКИ.ИмяРеквизита]);
				КонецЕсли;
			КонецЕсли;
			
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

Процедура УстановитьСвойстваПолейВвода(ИнформацияОВидеКИ, Элемент, Форма, ИмяРеквизита, ОбработкаНавигационнойСсылки)
	
	Если ИнформацияОВидеКИ.Тип = Перечисления.ТипыКонтактнойИнформации.Адрес Тогда
		Если Элемент.Вид = ВидПоляФормы.ПолеВвода Тогда
			Если ИнформацияОВидеКИ.ВидРедактирования = "ПолеВвода" Тогда
				Элемент.КнопкаВыпадающегоСписка = Истина;
				Элемент.Ширина = 70;
			ИначеЕсли ИнформацияОВидеКИ.ВидРедактирования = "Диалог" Тогда
				Элемент.Ширина = 73;
			Иначе
				Элемент.КнопкаВыпадающегоСписка = Истина;
				Элемент.Ширина = 68;
			КонецЕсли;
		ИначеЕсли Элемент.Вид = ВидПоляФормы.ПолеНадписи Тогда
			Элемент.Ширина = 73;
		КонецЕсли;
		
	ИначеЕсли ИнформацияОВидеКИ.Тип = Перечисления.ТипыКонтактнойИнформации.Телефон
		Или ИнформацияОВидеКИ.Тип = Перечисления.ТипыКонтактнойИнформации.Факс Тогда
		
		Если ИнформацияОВидеКИ.ВидРедактирования = "ПолеВвода" Тогда
			Элемент.Ширина = 40;
		Иначе
			Элемент.Ширина = 38;
		КонецЕсли;
		
		Если ИнформацияОВидеКИ.ВводитьНомерПоМаске Тогда 
			НомерТелефонаСоответствуетМаске = УправлениеКонтактнойИнформациейСлужебный.НомерТелефонаСоответствуетМаске(Форма[ИмяРеквизита], ИнформацияОВидеКИ.МаскаНомераТелефона);	
			Если ПустаяСтрока(Форма[ИмяРеквизита]) ИЛИ НомерТелефонаСоответствуетМаске Тогда
				Элемент.Маска = ИнформацияОВидеКИ.МаскаНомераТелефона;
			КонецЕсли;
			
			ТаблицаКонтактнойИнформации = УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеКонтактнойИнформацииНаФорме(Форма);
			НайденныеСтроки = ТаблицаКонтактнойИнформации.НайтиСтроки(Новый Структура("ИмяРеквизита", ИмяРеквизита));
			Если НайденныеСтроки.Количество() > 0 Тогда
				НайденныеСтроки[0].Маска = ИнформацияОВидеКИ.МаскаНомераТелефона;
			КонецЕсли;
		КонецЕсли;
		
	ИначеЕсли ИнформацияОВидеКИ.Тип = Перечисления.ТипыКонтактнойИнформации.Другое Тогда
		Если ИнформацияОВидеКИ.ВидПоляДругое = "МногострочноеШирокое" Тогда
			Элемент.Высота = 3;
			Элемент.Ширина = 72;
			Элемент.МногострочныйРежим = Истина;
		ИначеЕсли ИнформацияОВидеКИ.ВидПоляДругое = "ОднострочноеШирокое" Тогда
			Элемент.Высота = 1;
			Элемент.Ширина = 72;
			Элемент.МногострочныйРежим = Ложь;
		Иначе // ОднострочноеУзкое
			Элемент.Высота = 1;
			Элемент.Ширина = 35;
			Элемент.МногострочныйРежим = Ложь;
		КонецЕсли;
	ИначеЕсли ИнформацияОВидеКИ.Тип = Перечисления.ТипыКонтактнойИнформации.ВебСтраница Тогда
		Если ОбработкаНавигационнойСсылки Тогда	
			Элемент.Ширина = 73;
		Иначе
			Элемент.Ширина = 40;
		КонецЕсли;
	Иначе
		Элемент.Ширина = 40;
	КонецЕсли;
	
КонецПроцедуры

Процедура ПунктКонтекстногоМенюПеремещения(ПредыдущийЭлемент, Форма, Направление, ИмяЭлементаДляРазмещения)
	
	Если Направление > 0 Тогда
		ИмяКоманды = "КонтекстноеМенюВверх" + ПредыдущийЭлемент.Имя;
	Иначе
		ИмяКоманды = "КонтекстноеМенюВниз" + ПредыдущийЭлемент.Имя;
	КонецЕсли;
	
	Команда = Форма.Команды.Добавить(ИмяКоманды);
	Кнопка = Форма.Элементы.Добавить(ИмяКоманды, Тип("КнопкаФормы"), ПредыдущийЭлемент.КонтекстноеМеню);
	
	Команда.Действие = "Подключаемый_КонтактнаяИнформацияВыполнитьКоманду";
	Если Направление > 0 Тогда 
		ТекстКоманды = НСтр("ru = 'Переместить вверх'");
		Кнопка.Картинка = БиблиотекаКартинок.ПереместитьВверх;
	Иначе
		ТекстКоманды = НСтр("ru = 'Переместить вниз'");
		Кнопка.Картинка = БиблиотекаКартинок.ПереместитьВниз;
	КонецЕсли;
	Кнопка.Заголовок = ТекстКоманды;
	Команда.Подсказка = ТекстКоманды;
	Кнопка.ИмяКоманды = ИмяКоманды;
	Команда.ИзменяетСохраняемыеДанные = Истина;
	Кнопка.Доступность = Истина;
	ПараметрыКонтактнойИнформации = ПараметрыКонтактнойИнформацииФормы(Форма.ПараметрыКонтактнойИнформации, ИмяЭлементаДляРазмещения);
	ПараметрыКонтактнойИнформации.ДобавленныеЭлементы.Добавить(ИмяКоманды, 1);
	ПараметрыКонтактнойИнформации.ДобавленныеЭлементы.Добавить(ИмяКоманды, 9, Истина);
	
КонецПроцедуры

Функция Группа(ИмяГруппы, Форма, Заголовок, ИмяЭлементаДляРазмещения, ИмяГруппыРодителя = "", ПорядокУдаления = 5)
	
	Группа = Форма.Элементы.Найти(ИмяГруппы);
	
	Если Группа = Неопределено Тогда
		ИмяРодителя = ?(ЗначениеЗаполнено(ИмяГруппыРодителя), ИмяГруппыРодителя, ИмяЭлементаДляРазмещения);
		Родитель = Родитель(Форма, ИмяРодителя);
		Группа = Форма.Элементы.Добавить(ИмяГруппы, Тип("ГруппаФормы"), Родитель);
		Группа.Вид = ВидГруппыФормы.ОбычнаяГруппа;
		Группа.Заголовок = Заголовок;
		Группа.ОтображатьЗаголовок = Ложь;
		Группа.РазрешитьИзменениеСостава = Ложь;
		Группа.Отображение = ОтображениеОбычнойГруппы.Нет;
		Группа.Группировка = ГруппировкаПодчиненныхЭлементовФормы.ГоризонтальнаяВсегда;
		ПараметрыКонтактнойИнформации = ПараметрыКонтактнойИнформацииФормы(Форма.ПараметрыКонтактнойИнформации, ИмяЭлементаДляРазмещения);
		ПараметрыКонтактнойИнформации.ДобавленныеЭлементы.Добавить(ИмяГруппы, ПорядокУдаления);
	КонецЕсли;
	
	Возврат Группа;
	
КонецФункции

Процедура ПроверитьНаличиеРеквизитовКонтактнойИнформации(Форма, МассивДобавляемыхРеквизитов)
	
	СписокРеквизитовФормы = Форма.ПолучитьРеквизиты();
	
	СоздатьПараметрыКонтактнойИнформации = Истина;
	СоздатьТаблицуКонтактнойИнформации = Истина;
	Для Каждого Реквизит Из СписокРеквизитовФормы Цикл
		Если Реквизит.Имя = "ПараметрыКонтактнойИнформации" Тогда
			СоздатьПараметрыКонтактнойИнформации = Ложь;
		ИначеЕсли Реквизит.Имя = "КонтактнаяИнформацияОписаниеДополнительныхРеквизитов" Тогда
			СоздатьТаблицуКонтактнойИнформации = Ложь;
		КонецЕсли;
	КонецЦикла;
	
	Строка500 = Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(500));
	ИмяОписания = "КонтактнаяИнформацияОписаниеДополнительныхРеквизитов";
	
	Если СоздатьТаблицуКонтактнойИнформации Тогда
		
		// Создадим таблицу значений
		ИмяОписания = "КонтактнаяИнформацияОписаниеДополнительныхРеквизитов";
		МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы(ИмяОписания, Новый ОписаниеТипов("ТаблицаЗначений")));
		МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("ИмяРеквизита", Строка500, ИмяОписания));
		МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("ИмяРеквизитаКомментарий", Строка500, ИмяОписания));
		МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("Вид", Новый ОписаниеТипов("СправочникСсылка.ВидыКонтактнойИнформации"), ИмяОписания));
		МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("Тип", Новый ОписаниеТипов("ПеречислениеСсылка.ТипыКонтактнойИнформации"), ИмяОписания));
		МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("Значение", Новый ОписаниеТипов("Строка"), ИмяОписания));
		МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("Представление", Строка500, ИмяОписания));
		МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("Комментарий", Новый ОписаниеТипов("Строка"), ИмяОписания));
		МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("ЭтоРеквизитТабличнойЧасти", Новый ОписаниеТипов("Булево"), ИмяОписания));
		МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("ЭтоИсторическаяКонтактнаяИнформация", Новый ОписаниеТипов("Булево"), ИмяОписания));
		МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("ДействуетС", Новый ОписаниеТипов("Дата"), ИмяОписания));
		МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("ХранитьИсториюИзменений", Новый ОписаниеТипов("Булево"), ИмяОписания));
		МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("ИмяЭлементаДляРазмещения", Строка500, ИмяОписания));
		МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("МеждународныйФорматАдреса", Новый ОписаниеТипов("Булево"), ИмяОписания));
		МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("Маска", ОбщегоНазначения.ОписаниеТипаСтрока(100), ИмяОписания));
	Иначе
		РеквизитыТаблицы = Форма.ПолучитьРеквизиты("КонтактнаяИнформацияОписаниеДополнительныхРеквизитов");
		РеквизитыДляСоздания = Новый Соответствие;
		РеквизитыДляСоздания.Вставить("ИмяЭлементаДляРазмещения",            Истина);
		РеквизитыДляСоздания.Вставить("ИмяРеквизитаКомментарий",             Истина);
		РеквизитыДляСоздания.Вставить("ХранитьИсториюИзменений",             Истина);
		РеквизитыДляСоздания.Вставить("ДействуетС",                          Истина);
		РеквизитыДляСоздания.Вставить("ЭтоИсторическаяКонтактнаяИнформация", Истина);
		РеквизитыДляСоздания.Вставить("Значение",                            Истина);
		РеквизитыДляСоздания.Вставить("МеждународныйФорматАдреса",           Истина);
		РеквизитыДляСоздания.Вставить("Маска",           Истина);
		
		Для Каждого Реквизит Из РеквизитыТаблицы Цикл
			Если РеквизитыДляСоздания[Реквизит.Имя] <> Неопределено Тогда
				РеквизитыДляСоздания[Реквизит.Имя] = Ложь;
			КонецЕсли;
		КонецЦикла;
		
		Если РеквизитыДляСоздания["Значение"] Тогда
			МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("Значение", Новый ОписаниеТипов("Строка"), ИмяОписания));
		КонецЕсли;
		
		Если РеквизитыДляСоздания["МеждународныйФорматАдреса"] Тогда
			МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("МеждународныйФорматАдреса", Новый ОписаниеТипов("Булево"), ИмяОписания));
		КонецЕсли;
		
		Если РеквизитыДляСоздания["ИмяЭлементаДляРазмещения"] Тогда
			МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("ИмяЭлементаДляРазмещения", Строка500, ИмяОписания));
		КонецЕсли;
		
		Если РеквизитыДляСоздания["ИмяРеквизитаКомментарий"] Тогда
			МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("ИмяРеквизитаКомментарий", Строка500, ИмяОписания));
		КонецЕсли;
		
		Если РеквизитыДляСоздания["ХранитьИсториюИзменений"] Тогда
			МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("ХранитьИсториюИзменений", Новый ОписаниеТипов("Булево"), ИмяОписания));
		КонецЕсли;
		
		Если РеквизитыДляСоздания["ДействуетС"] Тогда
			МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("ДействуетС", Новый ОписаниеТипов("Дата"), ИмяОписания));
		КонецЕсли;
		
		Если РеквизитыДляСоздания["Маска"] Тогда
			МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("Маска", ОбщегоНазначения.ОписаниеТипаСтрока(100), ИмяОписания));
		КонецЕсли;
		
		Если РеквизитыДляСоздания["ЭтоИсторическаяКонтактнаяИнформация"] Тогда
			МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("ЭтоИсторическаяКонтактнаяИнформация", Новый ОписаниеТипов("Булево"), ИмяОписания));
		КонецЕсли;
		
	КонецЕсли;
	
	Если СоздатьПараметрыКонтактнойИнформации Тогда
		МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("ПараметрыКонтактнойИнформации", Новый ОписаниеТипов()));
	КонецЕсли;
	
КонецПроцедуры

Процедура УстановитьЗначенияРеквизитовПроверки(Объект, НастройкиПроверки = Неопределено)
	
	Объект.ПроверятьКорректность = ?(НастройкиПроверки = Неопределено, Ложь, НастройкиПроверки.ПроверятьКорректность);
	
	Объект.ТолькоНациональныйАдрес = Ложь;
	Объект.ВключатьСтрануВПредставление = Ложь;
	Объект.СкрыватьНеактуальныеАдреса = Ложь;
	
КонецПроцедуры

Функция НаименованиеДляФормированияИдентификатора(Объект) Экспорт
	
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.Мультиязычность") Тогда
		
		МодульМультиязычностьСервер = ОбщегоНазначения.ОбщийМодуль("МультиязычностьСервер");
		СуффиксТекущегоЯзыка = МодульМультиязычностьСервер.СуффиксТекущегоЯзыка();
		
		Возврат ?(ЗначениеЗаполнено(СуффиксТекущегоЯзыка),
			Объект["Наименование"+ СуффиксТекущегоЯзыка],
			Объект.Наименование);
		
	КонецЕсли;
	
	Возврат Объект.Наименование;

КонецФункции

Процедура ДобавитьРеквизитВОписание(Форма, СтрокаКонтактнойИнформации, ДанныеВидаКонтактнойИнформации, ЭтоНовыйВидКИ,
	ЭтоРеквизитТабличнойЧасти = Ложь, ЗаполнятьЗначениеРеквизита = Истина, ИмяЭлементаДляРазмещения = "ГруппаКонтактнаяИнформация")
	
	ТаблицаОписанияДополнительныхРеквизитов = УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеКонтактнойИнформацииНаФорме(Форма);
	НоваяСтрока = ТаблицаОписанияДополнительныхРеквизитов.Добавить();
	НоваяСтрока.ИмяРеквизита  = СтрокаКонтактнойИнформации.ИмяРеквизита;
	НоваяСтрока.Вид           = СтрокаКонтактнойИнформации.Вид;
	НоваяСтрока.Тип           = СтрокаКонтактнойИнформации.Тип;
	НоваяСтрока.ИмяЭлементаДляРазмещения  = ИмяЭлементаДляРазмещения;
	НоваяСтрока.ЭтоРеквизитТабличнойЧасти = ЭтоРеквизитТабличнойЧасти;
	
	Если НоваяСтрока.Свойство("ЭтоИсторическаяКонтактнаяИнформация") Тогда
		НоваяСтрока.ЭтоИсторическаяКонтактнаяИнформация = СтрокаКонтактнойИнформации.ЭтоИсторическаяКонтактнаяИнформация;
	КонецЕсли;
	
	Если НоваяСтрока.Свойство("ДействуетС") Тогда
		НоваяСтрока.ДействуетС = СтрокаКонтактнойИнформации.ДействуетС;
	КонецЕсли;
	
	Если НоваяСтрока.Свойство("ХранитьИсториюИзменений") Тогда
		НоваяСтрока.ХранитьИсториюИзменений = СтрокаКонтактнойИнформации.ХранитьИсториюИзменений;
	КонецЕсли;
	
	Если НоваяСтрока.Свойство("МеждународныйФорматАдреса") Тогда
		НоваяСтрока.МеждународныйФорматАдреса = СтрокаКонтактнойИнформации.МеждународныйФорматАдреса;
	КонецЕсли;
	
	НоваяСтрока.Значение      = СтрокаКонтактнойИнформации.Значение;
	НоваяСтрока.Представление = СтрокаКонтактнойИнформации.Представление;
	НоваяСтрока.Комментарий   = СтрокаКонтактнойИнформации.Комментарий;
	
	Если ЗаполнятьЗначениеРеквизита И Не ЭтоРеквизитТабличнойЧасти Тогда
		
		Если Форма.Элементы.Найти(СтрокаКонтактнойИнформации.ИмяРеквизита) <> Неопределено 
			И Форма.Элементы[СтрокаКонтактнойИнформации.ИмяРеквизита].Вид = ВидПоляФормы.ПолеНадписи Тогда
			ЭтоПолеНадписи = Истина;
		Иначе
			ЭтоПолеНадписи = Ложь;
		КонецЕсли;
		
		Если СтрокаКонтактнойИнформации.Тип = Перечисления.ТипыКонтактнойИнформации.Адрес
			И (СтрокаКонтактнойИнформации.ВидРедактирования = "Диалог" ИЛИ ЭтоПолеНадписи)
			И ПустаяСтрока(СтрокаКонтактнойИнформации.Представление) Тогда
			Форма[СтрокаКонтактнойИнформации.ИмяРеквизита] = УправлениеКонтактнойИнформациейКлиентСервер.ТекстПустогоАдресаВВидеГиперссылки();
		Иначе
			Форма[СтрокаКонтактнойИнформации.ИмяРеквизита] = СтрокаКонтактнойИнформации.Представление;
		КонецЕсли;
		
		ПараметрыКонтактнойИнформации = ПараметрыКонтактнойИнформацииФормы(Форма.ПараметрыКонтактнойИнформации, ИмяЭлементаДляРазмещения);
		ОбработкаНавигационнойСсылки = ПараметрыКонтактнойИнформации.ОбработкаНавигационнойСсылки;
		Если ДляТипаКонтактнойИнформацииЕстьПолеКомментарий(СтрокаКонтактнойИнформации.Тип, ОбработкаНавигационнойСсылки) Тогда
			РеквизитыДляЗаполнения = Новый Структура();    
			РеквизитыДляЗаполнения.Вставить("Комментарий" + СтрокаКонтактнойИнформации.ИмяРеквизита, СтрокаКонтактнойИнформации.Комментарий); 
			ЗаполнитьЗначенияСвойств(Форма, РеквизитыДляЗаполнения); 
		КонецЕсли;
		
	КонецЕсли;
	
	ДанныеВидаКонтактнойИнформации.Вставить("Ссылка", СтрокаКонтактнойИнформации.Вид);
	
	Если ЭтоНовыйВидКИ И ДанныеВидаКонтактнойИнформации.РазрешитьВводНесколькихЗначений И Не ЭтоРеквизитТабличнойЧасти И Не ДанныеВидаКонтактнойИнформации.ПометкаУдаления Тогда
		ПараметрыКонтактнойИнформации = ?(ПараметрыКонтактнойИнформации = Неопределено,
			ПараметрыКонтактнойИнформацииФормы(Форма.ПараметрыКонтактнойИнформации, ИмяЭлементаДляРазмещения),
			ПараметрыКонтактнойИнформации);
		Вид = СтрокаКонтактнойИнформации.Вид; // СправочникСсылка.ВидыКонтактнойИнформации
		Если ОбщегоНазначения.ЭтоМобильныйКлиент() Тогда
			ПараметрыКонтактнойИнформации.СписокДобавляемыхЭлементов.Добавить(ДанныеВидаКонтактнойИнформации, Строка(Вид));
		Иначе
			КартинкаТипа = КартинкаТипаКонтактнойИнформации(ДанныеВидаКонтактнойИнформации.Тип);
			ПараметрыКонтактнойИнформации.СписокДобавляемыхЭлементов.Добавить(ДанныеВидаКонтактнойИнформации, Строка(Вид),,КартинкаТипа);
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

Процедура УдалитьКомандыИЭлементыФормы(Форма, ИмяЭлементаДляРазмещения)
	
	ПараметрыКонтактнойИнформации = ПараметрыКонтактнойИнформацииФормы(Форма.ПараметрыКонтактнойИнформации, ИмяЭлементаДляРазмещения);
	ДобавленныеЭлементы = ПараметрыКонтактнойИнформации.ДобавленныеЭлементы;
	ДобавленныеЭлементы.СортироватьПоПредставлению();
	
	Для Каждого УдаляемыйЭлемент Из ДобавленныеЭлементы Цикл
		
		Если УдаляемыйЭлемент.Пометка Тогда
			Форма.Команды.Удалить(Форма.Команды[УдаляемыйЭлемент.Значение]);
		Иначе
			Форма.Элементы.Удалить(Форма.Элементы[УдаляемыйЭлемент.Значение]);
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

// Возвращает, доступно ли редактирование в диалоге для указанного типа контактной информации.
//
// Параметры:
//    Тип - ПеречислениеСсылка.ТипыКонтактнойИнформации - тип контактной информации.
//
// Возвращаемое значение:
//    Булево
//
Функция ДляТипаКонтактнойИнформацииДоступноРедактированиеВДиалоге(Тип)
	
	Возврат Тип = Перечисления.ТипыКонтактнойИнформации.Адрес 
		Или Тип = Перечисления.ТипыКонтактнойИнформации.Телефон
		Или Тип = Перечисления.ТипыКонтактнойИнформации.Факс;
	
КонецФункции

// Возвращает имена табличных частей документа по виду контактной информации.
//
// Параметры:
//    ТаблицаВидовКонтактнойИнформации - ТаблицаЗначений - список видов контактной информации:
//     * Вид - СправочникСсылка.ВидыКонтактнойИнформации - вид контактной информации.
//    ИмяОбъекта                       - Строка - полное имя объекта метаданного.
//
// Возвращаемое значение:
//    Соответствие - имена табличных части или пустая строка, если табличной части нет.
//
Функция ИменаТабличныхЧастейПоВидамКИ(ТаблицаВидовКонтактнойИнформации, ИмяОбъекта)
	
	Запрос = Новый Запрос;
	Запрос.Текст = "ВЫБРАТЬ
	|	ВидыКонтактнойИнформации.Вид КАК ВидКИ
	|ПОМЕСТИТЬ ВидыКИ
	|ИЗ
	|	&ТаблицаВидовКонтактнойИнформации КАК ВидыКонтактнойИнформации
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	ВЫБОР
	|		КОГДА ВидыКонтактнойИнформации.Родитель.ИмяПредопределенногоВида <> """"
	|		ТОГДА ВидыКонтактнойИнформации.Родитель.ИмяПредопределенногоВида
	|		ИНАЧЕ ВидыКонтактнойИнформации.Родитель.ИмяПредопределенныхДанных
	|	КОНЕЦ КАК ИмяТабличнойЧасти,
	|	ВидыКИ.ВидКИ КАК ВидКонтактнойИнформации
	|ИЗ
	|	ВидыКИ КАК ВидыКИ
	|		ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВидыКонтактнойИнформации КАК ВидыКонтактнойИнформации
	|		ПО ВидыКИ.ВидКИ = ВидыКонтактнойИнформации.Ссылка";
	
	Запрос.УстановитьПараметр("ТаблицаВидовКонтактнойИнформации", ТаблицаВидовКонтактнойИнформации);
	РезультатЗапроса = Запрос.Выполнить().Выбрать();
	
	Результат = Новый Соответствие;
	Пока РезультатЗапроса.Следующий() Цикл
		
		Если ЗначениеЗаполнено(РезультатЗапроса.ИмяТабличнойЧасти) Тогда
			ИмяТабличнойЧасти = Сред(РезультатЗапроса.ИмяТабличнойЧасти, СтрНайти(РезультатЗапроса.ИмяТабличнойЧасти, ИмяОбъекта) + СтрДлина(ИмяОбъекта));
		Иначе
			ИмяТабличнойЧасти = "";
		КонецЕсли;
		
		Результат.Вставить(РезультатЗапроса.ВидКонтактнойИнформации, ИмяТабличнойЧасти);
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции

// Проверяет на наличие в форме заполненных строк КИ того же вида (за исключением текущей).
//
Функция ЕстьДругиеЗаполненныеСтрокКИДанногоВида(Знач Форма, Знач ПроверяемаяСтрока, Знач ВидКонтактнойИнформации)
	
	ВсеСтрокиЭтогоВида = УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеКонтактнойИнформацииНаФорме(Форма).НайтиСтроки(
		Новый Структура("Вид", ВидКонтактнойИнформации));
	
	Для Каждого СтрокаВида Из ВсеСтрокиЭтогоВида Цикл
		
		Если СтрокаВида <> ПроверяемаяСтрока Тогда
			Представление = Форма[СтрокаВида.ИмяРеквизита];
			Если Не ПустаяСтрока(Представление) Тогда 
				Возврат Истина;
			КонецЕсли;
		КонецЕсли;
		
	КонецЦикла;
	
	Возврат Ложь;
КонецФункции

Процедура ВывестиСообщениеПользователю(ТекстСообщения, ИмяРеквизита, ПолеРеквизита = "")
	
	ИмяРеквизита = ?(ПустаяСтрока(ПолеРеквизита), ИмяРеквизита, "");
	ОбщегоНазначения.СообщитьПользователю(ТекстСообщения,, ПолеРеквизита, ИмяРеквизита);
	
КонецПроцедуры

////////////////////////////////////////////////////////////////////////////////
// Заполнение дополнительных реквизитов табличной части "Контактная информация".


Процедура УстановитьНаименованиеВидаКонтактнойИнформации(Знач Объект, Знач Наименование)
	
	НаименованияНаРазныхЯзыках = УправлениеКонтактнойИнформациейСлужебныйПовтИсп.НаименованияВидовКонтактнойИнформации();
	ИмяПредопределенногоВида = СокрЛП(Объект.ИмяПредопределенногоВида);
	
	Представление = НаименованияНаРазныхЯзыках.Получить(ОбщегоНазначения.КодОсновногоЯзыка())[ИмяПредопределенногоВида];
	Если ЗначениеЗаполнено(Представление) Тогда
		Объект.Наименование = Представление;
	ИначеЕсли ЗначениеЗаполнено(Наименование) Тогда
		Объект.Наименование = Наименование;
	КонецЕсли;
	
	ПредопределенныеДанныеОбъекта = Неопределено;
	
	ПараметрыЗаполнения = ОбновлениеИнформационнойБазыСлужебный.НаборПараметровДляЗаполненияОбъекта(Объект.Метаданные());
	ИмяКлючевогоРеквизита = ПараметрыЗаполнения.НастройкиПредопределенныхЭлементов.ПереопределяемыеНастройки.ИмяКлючевогоРеквизита;
	
	Если ЗначениеЗаполнено(ИмяКлючевогоРеквизита) Тогда
		
		ЗначениеКлючаОбъекта = Объект[ИмяКлючевогоРеквизита];
		
		Если ЗначениеЗаполнено(ЗначениеКлючаОбъекта) Тогда
			ПредопределенныеДанныеОбъекта = ПараметрыЗаполнения.ПредопределенныеДанные.Найти(ЗначениеКлючаОбъекта, ИмяКлючевогоРеквизита);
		КонецЕсли;
		
	КонецЕсли;
	
	Если ПредопределенныеДанныеОбъекта = Неопределено Или ПустаяСтрока(ИмяКлючевогоРеквизита) Тогда
		ПредопределенныеДанныеОбъекта = ПараметрыЗаполнения.ПредопределенныеДанные.Найти(ЗначениеКлючаОбъекта, "ИмяПредопределенныхДанных");
	КонецЕсли;
	
	Если ПустаяСтрока(Объект.Наименование) И ПредопределенныеДанныеОбъекта <> Неопределено Тогда
		
		Представление = ПредопределенныеДанныеОбъекта["Наименование" + "_" + ОбщегоНазначения.КодОсновногоЯзыка()];
		Если ПустаяСтрока(Представление) Тогда
			Представление = ПредопределенныеДанныеОбъекта["Наименование"];
		КонецЕсли;
		
		Если ЗначениеЗаполнено(Представление) Тогда
			Объект.Наименование = Представление;
		КонецЕсли;
		
	КонецЕсли;
	
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.Мультиязычность") Тогда
		МодульМультиязычностьСервер = ОбщегоНазначения.ОбщийМодуль("МультиязычностьСервер");
		СведенияОбЯзыках = МодульМультиязычностьСервер.СведенияОбЯзыках();
		
		ПредставлениеЯзык1 = "";
		ПредставлениеЯзык2 = "";
		
		Если ПредопределенныеДанныеОбъекта <> Неопределено Тогда
			
			Если ЗначениеЗаполнено(СведенияОбЯзыках.Язык1) Тогда
				ПредставлениеЯзык1 = ПредопределенныеДанныеОбъекта["Наименование" + "_" + СведенияОбЯзыках.Язык1];
			КонецЕсли;
			Если ЗначениеЗаполнено(СведенияОбЯзыках.Язык2) Тогда
				ПредставлениеЯзык2 = ПредопределенныеДанныеОбъекта["Наименование" + "_" + СведенияОбЯзыках.Язык2];
			КонецЕсли;
			
		КонецЕсли;
		
		Если ПустаяСтрока(ПредставлениеЯзык1) Тогда
			
			ПредставленияЯзыка1 = НаименованияНаРазныхЯзыках.Получить(МодульМультиязычностьСервер.КодПервогоДополнительногоЯзыкаИнформационнойБазы());
			Если ТипЗнч(ПредставленияЯзыка1) = Тип("Соответствие") Тогда
				ПредставлениеЯзык1 = ПредставленияЯзыка1.Получить(ИмяПредопределенногоВида);
			КонецЕсли;
			
		КонецЕсли;
		
		Если ПустаяСтрока(ПредставлениеЯзык2) Тогда
			ПредставленияЯзыка2 = НаименованияНаРазныхЯзыках.Получить(МодульМультиязычностьСервер.КодВторогоДополнительногоЯзыкаИнформационнойБазы());
			Если ТипЗнч(ПредставленияЯзыка2) = Тип("Соответствие") Тогда
				ПредставлениеЯзык2 = ПредставленияЯзыка2.Получить(ИмяПредопределенногоВида);
			КонецЕсли;
		КонецЕсли;
		
		Объект.НаименованиеЯзык1 = ?(ЗначениеЗаполнено(ПредставлениеЯзык1), ПредставлениеЯзык1, Объект.Наименование);
		Объект.НаименованиеЯзык2 = ?(ЗначениеЗаполнено(ПредставлениеЯзык2), ПредставлениеЯзык2, Объект.Наименование);
		
	КонецЕсли;
	
КонецПроцедуры

Процедура КонвертацияКонтактнойИнформацииВJSON(КонтактнаяИнформация)
	
	// Конвертация
	Для Каждого СтрокаКИ Из КонтактнаяИнформация Цикл
		Если ПустаяСтрока(СтрокаКИ.Значение) Тогда
			Если ЗначениеЗаполнено(СтрокаКИ.ЗначенияПолей) Тогда
				
				НастройкиКонвертации = НастройкиКонвертацииКонтактнойИнформации();
				НастройкиКонвертации.ОбновлятьИдентификаторы             = Ложь;
				НастройкиКонвертации.ВосстанавливатьКонтактнуюИнформацию = Ложь;
				НастройкиКонвертации.Представление                       = СтрокаКИ.Представление;
				
				КонтактнаяИнформацияПоПолям = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияВСтруктуруJSON(СтрокаКИ.ЗначенияПолей,
					СтрокаКИ.Тип, НастройкиКонвертации);
				
				Если СтрокаКИ.Тип = Перечисления.ТипыКонтактнойИнформации.Адрес
				   И УправлениеКонтактнойИнформациейКлиентСервер.ЭтоАдресВСвободнойФорме(КонтактнаяИнформацияПоПолям.AddressType) Тогда
						Продолжить;
				КонецЕсли;
				
				Если ПустаяСтрока(КонтактнаяИнформацияПоПолям.value) Тогда
					КонтактнаяИнформацияПоПолям.value = СтрокаКИ.Представление;
				КонецЕсли;
				
				Если ПустаяСтрока(КонтактнаяИнформацияПоПолям.comment) И ЗначениеЗаполнено(СтрокаКИ.Комментарий) Тогда
					КонтактнаяИнформацияПоПолям.comment = СтрокаКИ.Комментарий;
				КонецЕсли;
				
				СтрокаКИ.Значение = УправлениеКонтактнойИнформациейСлужебный.СтруктураВСтрокуJSON(КонтактнаяИнформацияПоПолям);
				
			КонецЕсли;
			
		КонецЕсли;
		
		Если ПустаяСтрока(СтрокаКИ.Наименование) Тогда
			СтрокаКИ.Наименование = СтрокаКИ.ПредставлениеНаОсновномЯзыке;
		КонецЕсли;
		
	КонецЦикла;

КонецПроцедуры

Функция НастройкиКонвертацииКонтактнойИнформации() Экспорт
	
	Результат = Новый Структура();
	Результат.Вставить("ОбновлятьИдентификаторы",             Истина);
	Результат.Вставить("ВосстанавливатьКонтактнуюИнформацию", Истина);
	Результат.Вставить("Представление",                       "");
	Возврат Результат;
	
КонецФункции

Функция БазовыеСведенияКонтактнойИнформации(КонтактнаяИнформация = Неопределено) Экспорт
	
	Результат = БазовыеПоляКонтактнойИнформации();
	Если КонтактнаяИнформация = Неопределено Тогда
		Возврат Результат;
	КонецЕсли;
	
	ПоляКонтактнойИнформации = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияВСтруктуруJSON(КонтактнаяИнформация);
	ТипКонтактнойИнформации = ТипКонтактнойИнформации(КонтактнаяИнформация);
	
	Результат.Представление           = Строка(ПоляКонтактнойИнформации.Value);
	Результат.Комментарий             = Строка(ПоляКонтактнойИнформации.Comment);
	Результат.ТипКонтактнойИнформации = ТипКонтактнойИнформации;
	
	Возврат Результат;
	
КонецФункции

// Возвращаемое значение:
//  Структура:
//    * Представление - Строка
//    * ТипКонтактнойИнформации - ПеречислениеСсылка.ТипыКонтактнойИнформации
//                              - Неопределено
//    * Комментарий - Строка
//
Функция БазовыеПоляКонтактнойИнформации()
	
	ПоляКонтактнойИнформации = Новый Структура;
	ПоляКонтактнойИнформации.Вставить("Представление",           "");
	ПоляКонтактнойИнформации.Вставить("ТипКонтактнойИнформации", Неопределено);
	ПоляКонтактнойИнформации.Вставить("Комментарий",             "");
	
	Возврат ПоляКонтактнойИнформации;
	
КонецФункции

// Возвращаемое значение:
//  Структура -  поля контактной информации для преобразования:
//   * ТипКонтактнойИнформации - ПеречислениеСсылка.ТипыКонтактнойИнформации
//                           - Неопределено
//   * ДанныеXML - Строка
//   * Представление - Строка 
//
Функция ПоляКонтактнойИнформацииДляПреобразования() Экспорт

	Результат = Новый Структура;
	Результат.Вставить("ТипКонтактнойИнформации", Неопределено);
	Результат.Вставить("ДанныеXML",               "");
	Результат.Вставить("Представление",           "");
	
	Возврат Результат;
	
КонецФункции

Процедура СоздатьЭлементыТабличнойЧасти(Знач Форма, Знач ИмяОбъекта, ИмяЭлементаДляРазмещения, 
	Знач СтрокаКонтактнойИнформации, Знач ДанныеВидаКонтактнойИнформации)
	
	ВидыКонтактнойИнформацииТЧ = Новый Массив;
	Для Каждого СтрокаТабличнойЧасти Из СтрокаКонтактнойИнформации.Строки Цикл
		ВидыКонтактнойИнформацииТЧ.Добавить(СтрокаТабличнойЧасти.Вид);
	КонецЦикла;
	ДанныеВидовКонтактнойИнформацииТЧ = УправлениеКонтактнойИнформациейСлужебный.ДанныеВидовКонтактнойИнформации(
		ВидыКонтактнойИнформацииТЧ);
	
	ИмяВидаКонтактнойИнформации = ДанныеВидаКонтактнойИнформации.ИмяПредопределенногоВида;
	Если ПустаяСтрока(ИмяВидаКонтактнойИнформации) Тогда
		ИмяВидаКонтактнойИнформации = ДанныеВидаКонтактнойИнформации.ИмяПредопределенныхДанных;
	КонецЕсли;
	Позиция = СтрНайти(ИмяВидаКонтактнойИнформации, ИмяОбъекта);
	ИмяТабличнойЧасти = Сред(ИмяВидаКонтактнойИнформации, Позиция + СтрДлина(ИмяОбъекта));
	ПредыдущийВидТЧ = Неопределено;
	
	Для Каждого СтрокаТабличнойЧасти Из СтрокаКонтактнойИнформации.Строки Цикл
		
		ВидКонтактнойИнформацииТЧ = СтрокаТабличнойЧасти.Вид;
		Если ВидКонтактнойИнформацииТЧ <> ПредыдущийВидТЧ Тогда
			
			ГруппаТабличнойЧасти = Форма.Элементы[ИмяТабличнойЧасти + "ГруппаКонтактнаяИнформация"];
			
			Элемент = Форма.Элементы.Добавить(СтрокаТабличнойЧасти.ИмяРеквизита, Тип("ПолеФормы"), ГруппаТабличнойЧасти);
			Элемент.Вид = ВидПоляФормы.ПолеВвода;
			Элемент.ПутьКДанным = "Объект." + ИмяТабличнойЧасти + "." + СтрокаТабличнойЧасти.ИмяРеквизита;
			
			Если ДляТипаКонтактнойИнформацииДоступноРедактированиеВДиалоге(СтрокаТабличнойЧасти.Тип) Тогда
				Элемент.КнопкаВыбора = Не СтрокаТабличнойЧасти.ПометкаУдаления;
				Если ВидКонтактнойИнформацииТЧ.ВидРедактирования = "Диалог" Тогда
					Элемент.РедактированиеТекста = Ложь;
				КонецЕсли;
				
				Элемент.УстановитьДействие("НачалоВыбора", "Подключаемый_КонтактнаяИнформацияНачалоВыбора");
			КонецЕсли;
			Элемент.УстановитьДействие("ПриИзменении", "Подключаемый_КонтактнаяИнформацияПриИзменении");
			
			Если СтрокаТабличнойЧасти.ПометкаУдаления Тогда
				Элемент.Шрифт = ШрифтыСтиля.ЗаголовокУдаленногоРеквизитаШрифт;
				Элемент.РедактированиеТекста = Ложь;
			КонецЕсли;
			
			Если ВидКонтактнойИнформацииТЧ.ОбязательноеЗаполнение Тогда
				Элемент.АвтоОтметкаНезаполненного = Не СтрокаТабличнойЧасти.ПометкаУдаления;
			КонецЕсли;
			
			ПараметрыКонтактнойИнформацииЭлемента = Форма.ПараметрыКонтактнойИнформации[ИмяЭлементаДляРазмещения]; // см. ПараметрыВыводаКонтактнойИнформации
			ПараметрыКонтактнойИнформацииЭлемента.ДобавленныеЭлементы.Добавить(СтрокаТабличнойЧасти.ИмяРеквизита, 2, Ложь);
			
			ДобавитьРеквизитВОписание(Форма, СтрокаТабличнойЧасти, ДанныеВидовКонтактнойИнформацииТЧ, Ложь, Истина,, ИмяЭлементаДляРазмещения);
			ПредыдущийВидТЧ = ВидКонтактнойИнформацииТЧ;
			
		КонецЕсли;
		
		Отбор = Новый Структура;
		Отбор.Вставить("ИдентификаторСтрокиТабличнойЧасти", СтрокаТабличнойЧасти.ИдентификаторСтрокиТабличнойЧасти);
		
		СтрокиТаблицы = Форма.Объект[ИмяТабличнойЧасти].НайтиСтроки(Отбор);
		
		Если СтрокиТаблицы.Количество() = 1 Тогда
			СтрокаТаблицы = СтрокиТаблицы[0];
			СтрокаТаблицы[СтрокаТабличнойЧасти.ИмяРеквизита]                   = СтрокаТабличнойЧасти.Представление;
			СтрокаТаблицы[СтрокаТабличнойЧасти.ИмяРеквизита + "Значение"]      = СтрокаТабличнойЧасти.Значение;
		КонецЕсли;
	КонецЦикла;

КонецПроцедуры

// Проверяет контактную информацию электронной почты и сообщает об ошибках. 
//
// Параметры:
//     АдресЭП      - Структура
//                  - Строка - контактная информацией.
//     ВидИнформации - СправочникСсылка.ВидыКонтактнойИнформации - вид контактной информации с настройками проверки.
//     ИмяРеквизита  - Строка - необязательно имя реквизита для привязки сообщения об ошибке.
//
// Возвращаемое значение:
//     Число - уровень ошибок: 0 - нет, 1 - неблокирующие, 2 - блокирующие.
//
Функция ОшибкиЗаполненияЭлектроннойПочты(АдресЭП, ВидИнформации, Знач ИмяРеквизита = "", ПолеРеквизита = "")
	
	ПроверятьКорректность = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ВидИнформации, "ПроверятьКорректность");
	
	Если Не ПроверятьКорректность Тогда
		Возврат 0;
	КонецЕсли;
	
	Если Не ЗначениеЗаполнено(АдресЭП) Тогда
		Возврат 0;
	КонецЕсли;
	
	СтрокаОшибки = "";
	ЭлектроннаяПочта = УправлениеКонтактнойИнформациейСлужебный.JSONВКонтактнуюИнформациюПоПолям(АдресЭП, Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты);
	
	Попытка
		Результат = ОбщегоНазначенияКлиентСервер.АдресаЭлектроннойПочтыИзСтроки(ЭлектроннаяПочта.Value);
		Если Результат.Количество() > 1 Тогда
			СтрокаОшибки = НСтр("ru = 'Допускается ввод только одного адреса электронной почты'");
		ИначеЕсли Результат.Количество() = 1 Тогда
			СтрокаОшибки = Результат[0].ОписаниеОшибки;
		КонецЕсли;
	Исключение
		СтрокаОшибки = ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
	КонецПопытки;
	
	Если Не ПустаяСтрока(СтрокаОшибки) Тогда
		ВывестиСообщениеПользователю(СтрокаОшибки, ИмяРеквизита, ПолеРеквизита);
		УровеньОшибки = ?(ПроверятьКорректность, 2, 1);
	Иначе
		УровеньОшибки = 0;
	КонецЕсли;
	
	Возврат УровеньОшибки;
	
КонецФункции

// Проверяет контактную информацию.
//
Функция ПроверитьЗаполнениеКонтактнойИнформации(Представление, Значение, ВидИнформации, ТипИнформации,
	ИмяРеквизита, Комментарий = Неопределено, ПутьКРеквизиту = "")
	
	Если ПустаяСтрока(Значение) Тогда
		
		Если ПустаяСтрока(Представление) Тогда
			Возврат 0;
		КонецЕсли;
		
		ВидРедактирования = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ВидИнформации, "ВидРедактирования");
		Если ВидРедактирования = "Диалог" И СтрСравнить(Представление, УправлениеКонтактнойИнформациейКлиентСервер.ТекстПустогоАдресаВВидеГиперссылки()) = 0 Тогда
			Возврат 0;
		КонецЕсли;
		
		КонтактнаяИнформация = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияПоПредставлению(Представление, ВидИнформации);
		Значение = ?(ТипЗнч(КонтактнаяИнформация) = Тип("Структура"), УправлениеКонтактнойИнформациейСлужебный.СтруктураВСтрокуJSON(КонтактнаяИнформация), "");
		
	ИначеЕсли УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВXML(Значение) Тогда
		
		Значение = КонтактнаяИнформацияВJSON(Значение, ВидИнформации);
		
	КонецЕсли;
	
	// Проверка
	Если ТипИнформации = Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты Тогда
		УровеньОшибок = ОшибкиЗаполненияЭлектроннойПочты(Значение, ВидИнформации, ИмяРеквизита, ПутьКРеквизиту);
	ИначеЕсли ТипИнформации = Перечисления.ТипыКонтактнойИнформации.Адрес Тогда
		УровеньОшибок = ОшибкиЗаполненияАдреса(Значение, ВидИнформации, ИмяРеквизита, ПутьКРеквизиту);
	ИначеЕсли ТипИнформации = Перечисления.ТипыКонтактнойИнформации.Телефон 
		Или ТипИнформации = Перечисления.ТипыКонтактнойИнформации.Факс Тогда
		УровеньОшибок = ОшибкиЗаполненияТелефона(Значение, ВидИнформации, ИмяРеквизита);
	ИначеЕсли ТипИнформации = Перечисления.ТипыКонтактнойИнформации.ВебСтраница Тогда
		УровеньОшибок = ОшибкиЗаполненияВебСтраницы(Значение, ВидИнформации, ИмяРеквизита);
	Иначе
		УровеньОшибок = 0; // Другое не проверяем.
	КонецЕсли;
	
	Возврат УровеньОшибок;
	
КонецФункции

// Получение и коррекция контактной информации
Процедура СкорректироватьКонтактнуюИнформацию(Форма, СтрокаКИ)
	
	РезультатПреобразования = Новый Структура;
	
	Если ПустаяСтрока(СтрокаКИ.Значение) Тогда
		
		Если ПустаяСтрока(СтрокаКИ.Представление) И ЗначениеЗаполнено(СтрокаКИ.ЗначенияПолей) Тогда
			СтрокаКИ.Представление = УправлениеКонтактнойИнформациейСлужебный.ПредставлениеКонтактнойИнформации(СтрокаКИ.ЗначенияПолей);
		КонецЕсли;
		
		// Локализация
		Если УправлениеКонтактнойИнформациейСлужебныйПовтИсп.ДоступенМодульЛокализации() Тогда
			МодульУправлениеКонтактнойИнформациейЛокализация = ОбщегоНазначения.ОбщийМодуль("УправлениеКонтактнойИнформациейЛокализация");
		
			НастройкиКонвертации = НастройкиКонвертацииКонтактнойИнформации();
			НастройкиКонвертации.Представление                       = СтрокаКИ.Представление;
			НастройкиКонвертации.ВосстанавливатьКонтактнуюИнформацию = Ложь;
			
			Результат = МодульУправлениеКонтактнойИнформациейЛокализация.КонтактнаяИнформацияИзXML(СтрокаКИ.ЗначенияПолей, 
				СтрокаКИ.Вид, РезультатПреобразования, НастройкиКонвертации);
			СтрокаКИ.Комментарий = ?(ЗначениеЗаполнено(Результат.Комментарий), Результат.Комментарий, "");
			
			Если РезультатПреобразования.Количество() = 0 Тогда
				Возврат;
			КонецЕсли;
				
			Если Не РезультатПреобразования.Свойство("СведенияИсправлены") ИЛИ РезультатПреобразования.СведенияИсправлены = Ложь Тогда
				Возврат;
			КонецЕсли;
			
			Если РезультатПреобразования.СведенияИсправлены Тогда
				СтрокаКИ.ЗначенияПолей = МодульУправлениеКонтактнойИнформациейЛокализация.КонтактнаяИнформацияXDTOВXML(Результат);
			КонецЕсли;
	
			Если РезультатПреобразования.Свойство("ТекстОшибки") Тогда
				ОбщегоНазначения.СообщитьПользователю(РезультатПреобразования.ТекстОшибки, , СтрокаКИ.ИмяРеквизита);
			КонецЕсли;
			
			Форма.Модифицированность = Истина;
		КонецЕсли;
		// Конец Локализация
		
	Иначе
		
		СтрокаКИ.Комментарий = КомментарийКонтактнойИнформации(СтрокаКИ.Значение);
		
		Если ПустаяСтрока(СтрокаКИ.Представление) Тогда
			СтрокаКИ.Представление = ПредставлениеКонтактнойИнформации(СтрокаКИ.Значение);
		КонецЕсли;
		
	КонецЕсли;
	
КонецПроцедуры

// Проверяет контактную информацию адреса и сообщает об ошибках. Возвращает флаг наличия ошибок.
//
// Параметры:
//     Источник      - ОбъектXDTO - контактная информацией.
//     ВидИнформации - СправочникСсылка.ВидыКонтактнойИнформации - вид контактной информации с настройками проверки.
//     ИмяРеквизита  - Строка - необязательно имя реквизита для привязки сообщения об ошибке.
//
// Возвращаемое значение:
//     Число - уровень ошибок: 0 - нет, 1 - неблокирующие, 2 - блокирующие.
//
Функция ОшибкиЗаполненияАдреса(Источник, ВидИнформации, ИмяРеквизита = "", ПолеРеквизита = "")
	
	ПроверятьКорректность = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ВидИнформации, "ПроверятьКорректность");
	
	Если Не ПроверятьКорректность Тогда
		Возврат 0;
	КонецЕсли;
	ЕстьОшибки = Ложь;
	
	Если НЕ УправлениеКонтактнойИнформациейСлужебный.ЭтоНациональныйАдрес(Источник) Тогда
		Возврат 0;
	КонецЕсли;
	
	Если Метаданные.Обработки.Найти("РасширенныйВводКонтактнойИнформации") <> Неопределено Тогда
		СписокОшибок = Обработки["РасширенныйВводКонтактнойИнформации"].ОшибкиЗаполненияАдреса(Источник, ВидИнформации);
		Для Каждого Элемент Из СписокОшибок Цикл
			
			ВывестиСообщениеПользователю(Элемент.ТекстОшибки, ИмяРеквизита, ПолеРеквизита);
			ЕстьОшибки = Истина;
			
		КонецЦикла;
	КонецЕсли;
	
	Если ЕстьОшибки И ПроверятьКорректность Тогда
		Возврат 2;
	ИначеЕсли ЕстьОшибки Тогда
		Возврат 1;
	КонецЕсли;
	
	Возврат 0;
КонецФункции

// Проверяет контактную информацию телефона и сообщает об ошибках. Возвращает флаг наличия ошибок.
//
// Параметры:
//     Источник      - ОбъектXDTO - контактная информацией.
//     ВидИнформации - СправочникСсылка.ВидыКонтактнойИнформации - вид контактной информации с настройками проверки.
//     ИмяРеквизита  - Строка - необязательно имя реквизита для привязки сообщения об ошибке к реквизиту на форме.
//
// Возвращаемое значение:
//     Число - уровень ошибок: 0 - нет, 1 - неблокирующие, 2 - блокирующие.
//
Функция ОшибкиЗаполненияТелефона(Источник, ВидИнформации, ИмяРеквизита = "")
	
	ПроверятьКорректность = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ВидИнформации, "ПроверятьКорректность");
	
	Если Не ПроверятьКорректность Тогда
		Возврат 0;
	КонецЕсли;
		
	ЕстьОшибки = Ложь;
	
	СведенияОТелефоне = СведенияОТелефоне(Источник);
	
	МодульРаботаСАдресами = Неопределено;
	Если УправлениеКонтактнойИнформациейСлужебныйПовтИсп.ДоступныМодулиРаботаСАдресами()  Тогда 
		МодульРаботаСАдресами = ОбщегоНазначения.ОбщийМодуль("РаботаСАдресами");
	КонецЕсли;
	
	СписокОшибок  = УправлениеКонтактнойИнформациейКлиентСервер.ОшибкиЗаполненияТелефона(СведенияОТелефоне, МодульРаботаСАдресами);

	Для Каждого Элемент Из СписокОшибок Цикл
		
		Если ЗначениеЗаполнено(ИмяРеквизита) Тогда
			ВывестиСообщениеПользователю(Элемент.Представление, ИмяРеквизита);
		КонецЕсли;
		
		ЕстьОшибки = Истина;
	КонецЦикла;

	Если ЕстьОшибки И ПроверятьКорректность Тогда
		Возврат 2;
	ИначеЕсли ЕстьОшибки Тогда
		Возврат 1;
	КонецЕсли;
	
	Возврат 0;
	
КонецФункции

// Проверяет контактную информацию веб страницы и сообщает об ошибках. Возвращает флаг наличия ошибок.
//
// Параметры:
//     Источник      - ОбъектXDTO - контактная информацией.
//     ВидИнформации - СправочникСсылка.ВидыКонтактнойИнформации - вид контактной информации с настройками проверки.
//     ИмяРеквизита  - Строка - необязательно имя реквизита для привязки сообщения об ошибке.
//
// Возвращаемое значение:
//     Число - уровень ошибок: 0 - нет, 1 - неблокирующие, 2 - блокирующие.
//
Функция ОшибкиЗаполненияВебСтраницы(Источник, ВидИнформации, ИмяРеквизита = "")
	Возврат 0;
КонецФункции

Процедура ОбработкаЗаполненияКонтактнойИнформацииОбъекта(Объект, Знач ДанныеЗаполнения)
	
	Если ТипЗнч(ДанныеЗаполнения) <> Тип("Структура") Тогда
		Возврат;
	КонецЕсли;
	
	// Наименование, если есть в объекте-приемнике.
	Наименование = Неопределено;
	Если ДанныеЗаполнения.Свойство("Наименование", Наименование)
		И ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(Объект, "Наименование") Тогда
		Объект.Наименование = Наименование;
	КонецЕсли;
	
	// Таблица контактной информации, заполняется только если КИ не находится в другой ТЧ.
	КонтактнаяИнформация = Неопределено;
	Если ДанныеЗаполнения.Свойство("КонтактнаяИнформация", КонтактнаяИнформация) 
		И ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(Объект, "КонтактнаяИнформация") Тогда
		
		Если ТипЗнч(КонтактнаяИнформация) = Тип("ТаблицаЗначений") Тогда
			КолонкиТаблицы = КонтактнаяИнформация.Колонки;
		Иначе
			ТаблицаКонтактнаяИнформация = КонтактнаяИнформация.ВыгрузитьКолонки(); // ТаблицаЗначений
			КолонкиТаблицы = ТаблицаКонтактнаяИнформация.Колонки;
		КонецЕсли;
		
		Если КолонкиТаблицы.Найти("ИдентификаторСтрокиТабличнойЧасти") = Неопределено Тогда
			
			Для Каждого СтрокаКИ Из КонтактнаяИнформация Цикл
				НоваяСтрокаКИ = Объект.КонтактнаяИнформация.Добавить();
				ЗаполнитьЗначенияСвойств(НоваяСтрокаКИ, СтрокаКИ, , "ЗначенияПолей");
				НоваяСтрокаКИ.ЗначенияПолей = КонтактнаяИнформацияВXML(СтрокаКИ.ЗначенияПолей, СтрокаКИ.Представление, СтрокаКИ.Вид);
			КонецЦикла;
			
		КонецЕсли;
		
	КонецЕсли;
	
КонецПроцедуры

Функция Родитель(Форма, ИмяЭлементаДляРазмещения)
	
	Возврат ?(ПустаяСтрока(ИмяЭлементаДляРазмещения), Форма, Форма.Элементы[ИмяЭлементаДляРазмещения])
	
КонецФункции

// Описание параметров вывода контактной информации
// 
// Параметры:
//   Форма - ФормаКлиентскогоПриложения
//   ИмяЭлементаДляРазмещения - Строка
//                            - Неопределено
//   ПоложениеЗаголовкаКИ - Строка
//                        - ПоложениеЗаголовкаЭлементаФормы
//   ОтложеннаяИнициализация - Массив
//                           - Булево
//   ДополнительныеПараметры - см. ДополнительныеПараметрыВыводаКонтактнойИнформации
//
// Возвращаемое значение:
//  Структура:
//   * ГруппаДляРазмещения - Строка
//   * ПоложениеЗаголовка - Строка
//   * ДобавленныеРеквизиты - СписокЗначений
//   * ОтложеннаяИнициализация - Булево
//   * ИсключаемыеВиды - Массив
//                     - Неопределено
//   * ВыполненаОтложеннаяИнициализация - Булево
//   * ДобавленныеЭлементы - СписокЗначений
//   * СписокДобавляемыхЭлементов - СписокЗначений:
//       * Значение - Структура:
//         ** Ссылка - СправочникСсылка.ВидыКонтактнойИнформации
//       * Ключ - Строка
//   * МожноОтправлятьSMS - Булево
//   * Владелец - ЛюбаяСсылка
//   * ОбработкаНавигационнойСсылки - Булево
//   * СкрываемыеВиды - Массив
//                    - Неопределено
//   * ОписаниеКоманд - см. ОписаниеКоманд
//   * ОтображатьИконки - Булево
//   * РазмещеныНаФорме - Соответствие из КлючИЗначение:
//       * Ключ - СправочникСсылка.ВидыКонтактнойИнформации
//       * Значение - Булево
//                  - Неопределено
//   * РазрешитьДобавлениеПолей - Булево
//   * ШиринаПоляКомментарий - Число
//   * ПоложениеКнопкиДобавить - Строка - может принимать следующие значения: "Лево", "Право", "Авто".
//   * ГруппаДляРазмещенияОграниченаШириной - Булево
//
Функция ПараметрыВыводаКонтактнойИнформации(Форма, ИмяЭлементаДляРазмещения, ПоложениеЗаголовкаКИ,
	ОтложеннаяИнициализация, ДополнительныеПараметры)
	
	Если ТипЗнч(Форма.ПараметрыКонтактнойИнформации) <> Тип("Структура") Тогда
		Форма.ПараметрыКонтактнойИнформации = Новый Структура;
	КонецЕсли;
	
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ОтправкаSMS") Тогда
		МодульОтправкаSMS  = ОбщегоНазначения.ОбщийМодуль("ОтправкаSMS");
		МожноОтправлятьSMS = МодульОтправкаSMS.ДоступнаОтправкаSMS();
	Иначе
		МожноОтправлятьSMS = Ложь;
	КонецЕсли;
	
	ПараметрыКонтактнойИнформации = Новый Структура;
	ПараметрыКонтактнойИнформации.Вставить("ГруппаДляРазмещения",              ИмяЭлементаДляРазмещения);
	ПараметрыКонтактнойИнформации.Вставить("ПоложениеЗаголовка",               ЗначениеПоложенияЗаголовкаКИ(ПоложениеЗаголовкаКИ));
	ПараметрыКонтактнойИнформации.Вставить("ДобавленныеРеквизиты",             Новый СписокЗначений); 
	ПараметрыКонтактнойИнформации.Вставить("ОтложеннаяИнициализация",          ОтложеннаяИнициализация);
	ПараметрыКонтактнойИнформации.Вставить("ИсключаемыеВиды",                  ДополнительныеПараметры.ИсключаемыеВиды);
	ПараметрыКонтактнойИнформации.Вставить("ВыполненаОтложеннаяИнициализация", Ложь);
	ПараметрыКонтактнойИнформации.Вставить("ДобавленныеЭлементы",              Новый СписокЗначений);
	ПараметрыКонтактнойИнформации.Вставить("СписокДобавляемыхЭлементов",       Новый СписокЗначений);
	ПараметрыКонтактнойИнформации.Вставить("МожноОтправлятьSMS",               МожноОтправлятьSMS);
	ПараметрыКонтактнойИнформации.Вставить("Владелец",                         Неопределено);
	ПараметрыКонтактнойИнформации.Вставить("ОбработкаНавигационнойСсылки",     Ложь);
	ПараметрыКонтактнойИнформации.Вставить("СкрываемыеВиды",                   ДополнительныеПараметры.СкрываемыеВиды);
	ПараметрыКонтактнойИнформации.Вставить("ОписаниеКоманд",                   ДополнительныеПараметры.ОписаниеКоманд);
	ПараметрыКонтактнойИнформации.Вставить("ОтображатьИконки",                 ДополнительныеПараметры.ОтображатьИконки);
	ПараметрыКонтактнойИнформации.Вставить("РазмещеныНаФорме",                 ДополнительныеПараметры.РазмещеныНаФорме);
	ПараметрыКонтактнойИнформации.Вставить("РазрешитьДобавлениеПолей",         ДополнительныеПараметры.РазрешитьДобавлениеПолей);
	ПараметрыКонтактнойИнформации.Вставить("ШиринаПоляКомментарий",            ДополнительныеПараметры.ШиринаПоляКомментарий);
	ПараметрыКонтактнойИнформации.Вставить("ПоложениеКнопкиДобавить",          Строка(ДополнительныеПараметры.ПоложениеКнопкиДобавить));
	ПараметрыКонтактнойИнформации.Вставить("ГруппаДляРазмещенияОграниченаШириной", ГруппаДляРазмещенияОграниченаШириной(Форма.Элементы[ИмяЭлементаДляРазмещения]));
	
	ПараметрыАдреса = Новый Структура("ТипПомещения, Страна, Индекс", "Квартира");
	ПараметрыКонтактнойИнформации.Вставить("ПараметрыАдреса", ПараметрыАдреса);
	
	Форма.ПараметрыКонтактнойИнформации.Вставить(ИмяЭлементаДляРазмещения, ПараметрыКонтактнойИнформации);
	Возврат Форма.ПараметрыКонтактнойИнформации[ИмяЭлементаДляРазмещения];
	
КонецФункции

// Проверяет наличие ограничения по ширине в группе, включая всех родителей группы.
// Ограничением читается ширина меньше 90
//
Функция ГруппаДляРазмещенияОграниченаШириной(Группа)

	ОграничениеПоШирине = Ложь;
	ПроверитьГруппуНаОграничениеПоШиринеРекурсивно(Группа, ОграничениеПоШирине);
	
	Возврат ОграничениеПоШирине;

КонецФункции

Процедура ПроверитьГруппуНаОграничениеПоШиринеРекурсивно(Группа, ОграничениеПоШирине)
	
	Если Группа.Ширина <> 0 И Группа.Ширина < 90 Тогда
		ОграничениеПоШирине = Истина;
	КонецЕсли;
	
	Если ТипЗнч(Группа) <> Тип("ФормаКлиентскогоПриложения") Тогда
		ПроверитьГруппуНаОграничениеПоШиринеРекурсивно(Группа.Родитель, ОграничениеПоШирине);
	КонецЕсли;
	
КонецПроцедуры

Функция ГруппаВидовКонтактнойИнформацииОбъекта(Знач ПолноеИмяОбъектаМетаданных)
	
	Возврат ВидКонтактнойИнформацииПоИмени(СтрЗаменить(ПолноеИмяОбъектаМетаданных, ".", ""));
	
КонецФункции

// Возвращает виды контактной информации по имени.
// Если имя не указано, то возвращается полный список программно предопределенных видов.
//
// Возвращаемое значение:
//  ТаблицаЗначений  - виды контактной информации, где:
//    * Имя - Строка - имя вида контактной информации.
//    * Ссылка - СправочникСсылка.ВидыКонтактнойИнформации - ссылка на элемент справочника виды контактной информации.
//
Функция ПредопределенныеВидыКонтактнойИнформации(Имя = "") Экспорт
	
	ТекстЗапроса = "ВЫБРАТЬ
		|	ВидыКонтактнойИнформации.ИмяПредопределенногоВида КАК Имя,
		|	ВидыКонтактнойИнформации.Ссылка КАК Ссылка
		|ИЗ
		|	Справочник.ВидыКонтактнойИнформации КАК ВидыКонтактнойИнформации
		|ГДЕ
		|	&Отбор";
	
	Запрос = Новый Запрос();
	Если ЗначениеЗаполнено(Имя) Тогда
		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&Отбор", "ВидыКонтактнойИнформации.ИмяПредопределенногоВида = &Имя");
		Запрос.УстановитьПараметр("Имя", Имя);
	Иначе
		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&Отбор", "ВидыКонтактнойИнформации.ИмяПредопределенногоВида <> """"");
	КонецЕсли;
	
	Запрос.Текст = ТекстЗапроса;
	Возврат Запрос.Выполнить().Выгрузить();
	
КонецФункции

// Определяет значение положения заголовка. Для поддержки локализованных конфигураций.
//
// Параметры:
//  ПоложениеЗаголовкаКИ - Строка - положения заголовка в текстовом представление на языке локализации.
// 
// Возвращаемое значение:
//  Строка - положения заголовка.
//
Функция ЗначениеПоложенияЗаголовкаКИ(ПоложениеЗаголовкаКИ)
	
	Если ПоложениеЗаголовкаЭлементаФормы.Лево = ПоложениеЗаголовкаКИ Тогда
		Возврат "ПоложениеЗаголовкаЭлементаФормы.Лево";
	ИначеЕсли ПоложениеЗаголовкаЭлементаФормы.Верх = ПоложениеЗаголовкаКИ Тогда
		Возврат "ПоложениеЗаголовкаЭлементаФормы.Верх";
	ИначеЕсли ПоложениеЗаголовкаЭлементаФормы.Низ = ПоложениеЗаголовкаКИ Тогда
		Возврат "ПоложениеЗаголовкаЭлементаФормы.Низ";
	ИначеЕсли ПоложениеЗаголовкаЭлементаФормы.Право = ПоложениеЗаголовкаКИ Тогда
		Возврат "ПоложениеЗаголовкаЭлементаФормы.Право";
	ИначеЕсли ПоложениеЗаголовкаЭлементаФормы.Нет = ПоложениеЗаголовкаКИ Тогда
		Возврат "ПоложениеЗаголовкаЭлементаФормы.Нет";
	ИначеЕсли ПоложениеЗаголовкаЭлементаФормы.Авто = ПоложениеЗаголовкаКИ Тогда
		Возврат "ПоложениеЗаголовкаЭлементаФормы.Авто";
	КонецЕсли;
	
	Возврат "";
	
КонецФункции

Процедура СоздатьДействие(Форма, ВидКонтактнойИнформации, ИмяРеквизита, ГруппаДействий, ИмяЭлементаДляРазмещения = "ГруппаКонтактнаяИнформация")

	Тип = ВидКонтактнойИнформации.Тип;
		
	ПараметрыКИ = ПараметрыКонтактнойИнформацииФормы(Форма.ПараметрыКонтактнойИнформации, ИмяЭлементаДляРазмещения);
	
	ОтображатьИсторию = ВидКонтактнойИнформации.ХранитьИсториюИзменений И Не ВидКонтактнойИнформации.ПометкаУдаления;
	КомандыДляВывода = УправлениеКонтактнойИнформациейКлиентСервер.КомандыДляВыводаНаФорму(ПараметрыКИ, Тип, 
		ВидКонтактнойИнформации.Вид, ОтображатьИсторию);

	КоличествоКоманд = КомандыДляВывода.Количество();
	Если КоличествоКоманд = 0 Тогда
		Если ПараметрыКИ.ГруппаДляРазмещенияОграниченаШириной Тогда
			Декорация = Форма.Элементы.Добавить("Отступ" + ИмяРеквизита, Тип("ДекорацияФормы"), ГруппаДействий);
			Декорация.Вид       = ВидДекорацииФормы.Картинка;
			Декорация.Ширина    = 3;
			Декорация.Заголовок = НСтр("ru='Отступ'");
			Декорация.Высота    = 1;
		КонецЕсли;
		Возврат;
	КонецЕсли;
	
	Если Тип = Перечисления.ТипыКонтактнойИнформации.Адрес И ВидКонтактнойИнформации.ВидРедактирования = "Диалог" Тогда	
		ПолеВвода = Форма.Элементы[ИмяРеквизита];		
		ПолеВвода.РасширеннаяПодсказка.Заголовок = УправлениеКонтактнойИнформациейКлиентСервер.РасширеннаяПодсказкаАдреса(
			КомандыДляВывода, ВидКонтактнойИнформации.Представление, ВидКонтактнойИнформации.Комментарий);	
		ПолеВвода.РасширеннаяПодсказка.УстановитьДействие("ОбработкаНавигационнойСсылки",
			 "Подключаемый_КонтактнаяИнформацияОбработкаНавигационнойСсылки");			
		Возврат;
	КонецЕсли;	
	
	ИмяКоманды = "Команда" + ИмяРеквизита;
	Команда = Форма.Команды.Добавить(ИмяКоманды);
	ПараметрыКИ.ДобавленныеЭлементы.Добавить(ИмяКоманды, 9, Истина);
	Команда.Отображение = ОтображениеКнопки.Картинка;
	Команда.Действие = "Подключаемый_КонтактнаяИнформацияВыполнитьКоманду";
	Элемент = Форма.Элементы.Добавить(ИмяКоманды, Тип("КнопкаФормы"), ГруппаДействий);
	ПараметрыКИ.ДобавленныеЭлементы.Добавить(ИмяКоманды, 2);
	Элемент.ИмяКоманды = ИмяКоманды;

	Если КоличествоКоманд = 1 Тогда
		Для Каждого КомандаВывода Из КомандыДляВывода Цикл
			ЗаполнитьЗначенияСвойств(Команда, КомандаВывода.Значение, , "Действие");
		КонецЦикла;
	ИначеЕсли КоличествоКоманд > 1 Тогда
		Команда.Картинка = БиблиотекаКартинок.МенюДополнительныеФункции;
	КонецЕсли;

КонецПроцедуры

// Возвращает параметры контактной информации на форме
// 
// Параметры:
//   ПараметрыКонтактнойИнформации - см. ПараметрыВыводаКонтактнойИнформации
//   ИмяЭлементаДляРазмещения - Строка
//                            - Неопределено
// 	
// Возвращаемое значение:
//   см. ПараметрыВыводаКонтактнойИнформации
// 	
Функция ПараметрыКонтактнойИнформацииФормы(ПараметрыКонтактнойИнформации, ИмяЭлементаДляРазмещения)
	
	Если НЕ ЗначениеЗаполнено(ИмяЭлементаДляРазмещения) ИЛИ НЕ ПараметрыКонтактнойИнформации.Свойство(ИмяЭлементаДляРазмещения) Тогда
		Для каждого ПерваяЗапись Из ПараметрыКонтактнойИнформации Цикл
			Возврат ПерваяЗапись.Значение;
		КонецЦикла;
		Возврат ПараметрыКонтактнойИнформации;
	КонецЕсли;
	
	Возврат ПараметрыКонтактнойИнформации[ИмяЭлементаДляРазмещения];
	
КонецФункции

Функция ОпределитьСледующуюСтроку(Форма, КонтактнаяИнформация, СтрокаКИ)
	
	Позиция = КонтактнаяИнформация.Индекс(СтрокаКИ) + 1;
	Пока Позиция < КонтактнаяИнформация.Количество() Цикл
		СледующаяСтрока = КонтактнаяИнформация.Получить(Позиция);
		Если СледующаяСтрока = Неопределено Тогда
			Возврат Неопределено;
		КонецЕсли;
		Если Форма.Элементы.Найти(СледующаяСтрока.ИмяРеквизита) <> Неопределено Тогда
			Возврат СледующаяСтрока;
		КонецЕсли;
		Позиция = Позиция + 1;
	КонецЦикла;
	
	Возврат Неопределено;
КонецФункции

Процедура ВосстановитьПустыеЗначениеПредставление(СтрокаКонтактнойИнформации) Экспорт
	
	Если ПустаяСтрока(СтрокаКонтактнойИнформации.Тип) Тогда
		СтрокаКонтактнойИнформации.Тип = УправлениеКонтактнойИнформациейСлужебныйПовтИсп.ТипВидаКонтактнойИнформации(
			СтрокаКонтактнойИнформации.Вид);
	КонецЕсли;
	
	// ЗначенияПолей может отсутствовать в строке контактной информации
	СведенияПолей = Новый Структура("ЗначенияПолей", Неопределено);
	ЗаполнитьЗначенияСвойств(СведенияПолей, СтрокаКонтактнойИнформации);
	ЕстьЗначенияПолей = (СведенияПолей.ЗначенияПолей <> Неопределено);
	
	ПустоеПредставление = ПустаяСтрока(СтрокаКонтактнойИнформации.Представление);
	ПустоеЗначение      = ПустаяСтрока(СтрокаКонтактнойИнформации.Значение);
	ПустыеЗначенияПолей = ?(ЕстьЗначенияПолей, ПустаяСтрока(СведенияПолей.ЗначенияПолей), Истина);
	
	ВсеПоляПустые = ПустоеПредставление И ПустоеЗначение И ПустыеЗначенияПолей;
	ВсеПоляЗаполнены = Не ПустоеПредставление И Не ПустоеЗначение И НЕ ПустыеЗначенияПолей;
	
	Если ВсеПоляПустые Или ВсеПоляЗаполнены Тогда
		Возврат;
	КонецЕсли;
	
	Если ПустоеПредставление Тогда
				
		ИсточникЗначений = ?(ПустыеЗначенияПолей, СтрокаКонтактнойИнформации.Значение, СтрокаКонтактнойИнформации.ЗначенияПолей);
		
		СтрокаКонтактнойИнформации.Представление = УправлениеКонтактнойИнформациейСлужебный.ПредставлениеКонтактнойИнформации(
			ИсточникЗначений);
		
	КонецЕсли;
	
	Если ПустоеЗначение Тогда
		
		Если Не ПустоеПредставление И ПустыеЗначенияПолей Тогда
			
			АдресПоПолям = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияПоПредставлению(
				СтрокаКонтактнойИнформации.Представление, СтрокаКонтактнойИнформации.Тип);
			СтрокаКонтактнойИнформации.Значение = УправлениеКонтактнойИнформациейСлужебный.СтруктураВСтрокуJSON(АдресПоПолям);
			
			Если ЕстьЗначенияПолей И УправлениеКонтактнойИнформациейСлужебныйПовтИсп.ДоступенМодульЛокализации() Тогда
				МодульУправлениеКонтактнойИнформациейЛокализация = ОбщегоНазначения.ОбщийМодуль("УправлениеКонтактнойИнформациейЛокализация");
				СтрокаКонтактнойИнформации.ЗначенияПолей = МодульУправлениеКонтактнойИнформациейЛокализация.КонтактнаяИнформацияИзJSONВXML(
					СтрокаКонтактнойИнформации.Значение, СтрокаКонтактнойИнформации.Тип);
			КонецЕсли;
			
		ИначеЕсли Не ПустыеЗначенияПолей Тогда
			
			СтрокаКонтактнойИнформации.Значение = КонтактнаяИнформацияВJSON(СтрокаКонтактнойИнформации.ЗначенияПолей,
				СтрокаКонтактнойИнформации.Тип);
			
		КонецЕсли;
	
	ИначеЕсли ПустыеЗначенияПолей И ЕстьЗначенияПолей Тогда
		
		СтрокаКонтактнойИнформации.ЗначенияПолей = КонтактнаяИнформацияВXML(СтрокаКонтактнойИнформации.Значение, 
			СтрокаКонтактнойИнформации.Представление, СтрокаКонтактнойИнформации.Вид);
			
	КонецЕсли;
	
КонецПроцедуры

// Приводит код страны к единому виду - строка длиной три символа.
//
Функция КодСтраныМира(Знач КодСтраны)
	
	Если ТипЗнч(КодСтраны)=Тип("Число") Тогда
		Возврат Формат(КодСтраны, "ЧЦ=3; ЧН=; ЧВН=; ЧГ=");
	КонецЕсли;
	
	Возврат Прав("000" + КодСтраны, 3);
КонецФункции

// Возвращает строку в кавычках.
//
Функция КонтрольКавычекВСтроке(Знач Строка)
	Возврат """" + СтрЗаменить(Строка, """", """""") + """";
КонецФункции

Процедура ОбновитьКонтекстноеМеню(Форма, ИмяЭлементаДляРазмещения)
	
	ПараметрыКонтактнойИнформации = Форма.ПараметрыКонтактнойИнформации[ИмяЭлементаДляРазмещения];  // см. ПараметрыВыводаКонтактнойИнформации
	ВсеСтроки = УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеКонтактнойИнформацииНаФорме(Форма);
	НайденныеСтроки = ВсеСтроки.НайтиСтроки( 
		Новый Структура("Тип, ЭтоРеквизитТабличнойЧасти", Перечисления.ТипыКонтактнойИнформации.Адрес, Ложь));
		
	ОбщееКоличествоКоманд = 0;
	Для Каждого СтрокаКИ Из ВсеСтроки Цикл
		
		Если ОбщееКоличествоКоманд > 50 Тогда // Ограничение для большого количества адресов на форме
			Прервать;
		КонецЕсли;
		
		Если СтрокаКИ.Тип <> Перечисления.ТипыКонтактнойИнформации.Адрес Тогда
			Продолжить;
		КонецЕсли;
		
		КонтекстноеПодменюКопироватьАдреса = Форма.Элементы.Найти("КонтекстноеПодменюКопироватьАдреса" + СтрокаКИ.ИмяРеквизита);
		Если КонтекстноеПодменюКопироватьАдреса = Неопределено Тогда
			Продолжить;
		КонецЕсли;
			
		КоличествоКомандВПодменю = 0;
		СписокАдресовВПодменю = Новый Соответствие();
		ДанныеАдреса = Новый Структура("Представление, Адрес", СтрокаКИ.Представление, СтрокаКИ.Значение);
		СписокАдресовВПодменю.Вставить(ВРег(СтрокаКИ.Представление), ДанныеАдреса);
		
		Для Каждого Адрес Из НайденныеСтроки Цикл
			
			Если КоличествоКомандВПодменю > 7 Тогда // Ограничение для большого количества адресов на форме
				Прервать;
			КонецЕсли;
			
			Если Адрес.ЭтоИсторическаяКонтактнаяИнформация Или Адрес.ИмяРеквизита = СтрокаКИ.ИмяРеквизита Тогда
				Продолжить;
			КонецЕсли;
			
			Если НЕ ЗначениеЗаполнено(Адрес.Представление) Тогда
				Продолжить;
			КонецЕсли;
			
			ИмяКоманды = "МенюПодменюАдрес" + СтрокаКИ.ИмяРеквизита + "_" + Адрес.ИмяРеквизита;
			Команда = Форма.Команды.Найти(ИмяКоманды);
			Если Команда = Неопределено Тогда
				Команда = Форма.Команды.Добавить(ИмяКоманды);
				Команда.Подсказка = НСтр("ru = 'Скопировать адрес'");
				Команда.Действие = "Подключаемый_КонтактнаяИнформацияВыполнитьКоманду";
				Команда.ИзменяетСохраняемыеДанные = Истина;
				
				ПараметрыКонтактнойИнформации.ДобавленныеЭлементы.Добавить(ИмяКоманды, 9, Истина);
				КоличествоКомандВПодменю = КоличествоКомандВПодменю + 1;
			КонецЕсли;
			
			ПредставлениеАдреса = ?(СтрокаКИ.МеждународныйФорматАдреса,
				СтроковыеФункции.СтрокаЛатиницей(Адрес.Представление), Адрес.Представление);
			
			Если СписокАдресовВПодменю[ВРег(Адрес.Представление)] <> Неопределено Тогда
				ПредставлениеАдреса = "";
			Иначе
				ДанныеАдреса = Новый Структура("Представление, Адрес", ПредставлениеАдреса, Адрес.Значение);
				СписокАдресовВПодменю.Вставить(ВРег(Адрес.Представление), ДанныеАдреса);
			КонецЕсли;
				
			ДобавитьКнопкуСкопироватьАдрес(Форма, ИмяКоманды, ПредставлениеАдреса, ПараметрыКонтактнойИнформации, 
				КонтекстноеПодменюКопироватьАдреса);
						
		КонецЦикла;
		
		Поле = Форма.Элементы[СтрокаКИ.ИмяРеквизита];
		Если Поле.Вид = ВидПоляФормы.ПолеВвода Тогда
			Поле.СписокВыбора.Очистить();
			ПредставлениеДляПоиска = ВРег(СтрокаКИ.Представление);
			Для Каждого ДанныеАдреса Из СписокАдресовВПодменю Цикл
				Если ДанныеАдреса.Ключ <> ПредставлениеДляПоиска Тогда
					Поле.СписокВыбора.Добавить(ДанныеАдреса.Значение, ДанныеАдреса.Значение.Представление);
				КонецЕсли;
			КонецЦикла;
		КонецЕсли;
		
		ОбщееКоличествоКоманд = ОбщееКоличествоКоманд + КоличествоКомандВПодменю;
	КонецЦикла;
	
КонецПроцедуры

Процедура ДобавитьКнопкуСкопироватьАдрес(Форма, ИмяКоманды, ЗаголовокЭлемента, ПараметрыКонтактнойИнформации, Подменю)
	
	ИмяЭлемента = Подменю.Имя + "_" + ИмяКоманды;
	Кнопка = Форма.Элементы.Найти(ИмяЭлемента);
	Если Кнопка = Неопределено Тогда
		Кнопка = Форма.Элементы.Добавить(ИмяЭлемента, Тип("КнопкаФормы"), Подменю);
		Кнопка.ИмяКоманды = ИмяКоманды;
		ДобавленныеЭлементы = ПараметрыКонтактнойИнформации.ДобавленныеЭлементы; // СписокЗначений
		ДобавленныеЭлементы.Добавить(ИмяЭлемента, 1);
	КонецЕсли;
	Кнопка.Заголовок = ЗаголовокЭлемента;
	Кнопка.Видимость = ЗначениеЗаполнено(ЗаголовокЭлемента);

КонецПроцедуры

Функция ОписаниеНовойКонтактнойИнформации(Знач Тип) Экспорт
	
	Если УправлениеКонтактнойИнформациейСлужебныйПовтИсп.ДоступныМодулиРаботаСАдресами() Тогда
		МодульРаботаСАдресамиКлиентСервер = ОбщегоНазначения.ОбщийМодуль("РаботаСАдресамиКлиентСервер");
		Возврат МодульРаботаСАдресамиКлиентСервер.ОписаниеНовойКонтактнойИнформации(Тип);
	КонецЕсли;
	
	Возврат УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеНовойКонтактнойИнформации(Тип);
	
КонецФункции

Функция КонтактнаяИнформацияИзРеквизитовФормы(Форма, Объект)
	
	КонтактнаяИнформация = НоваяКонтактнаяИнформация(Ложь);
	
	МетаданныеОбъекта = Объект.Ссылка.Метаданные();
	ИмяОбъектаМетаданных = МетаданныеОбъекта.Имя;
	ПолноеИмяОбъектаМетаданных = МетаданныеОбъекта.ПолноеИмя();
	ГруппаВидовКонтактнойИнформации = ГруппаВидовКонтактнойИнформацииОбъекта(ПолноеИмяОбъектаМетаданных);
	ИменаТабличныхЧастейПоВидамКИ = Неопределено;
	
	Для Каждого СтрокаТаблицы Из УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеКонтактнойИнформацииНаФорме(Форма) Цикл
		
		ИмяРеквизита  = СтрокаТаблицы.ИмяРеквизита;
		
		Элемент = Форма.Элементы.Найти(ИмяРеквизита); // РасширениеПоляФормыДляПоляНадписи
		Если Элемент <> Неопределено Тогда
			Если Элемент.Вид = ВидПоляФормы.ПолеНадписи И Элемент.Гиперссылка Тогда
				Если ПустаяСтрока(СтрокаТаблицы.Представление)
					ИЛИ СтрокаТаблицы.Представление = УправлениеКонтактнойИнформациейКлиентСервер.ТекстПустогоАдресаВВидеГиперссылки() Тогда
					Продолжить;
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;
		
		ВосстановитьПустыеЗначениеПредставление(СтрокаТаблицы);
		
		Если СтрокаТаблицы.ЭтоРеквизитТабличнойЧасти Тогда
			
			Если ИменаТабличныхЧастейПоВидамКИ = Неопределено Тогда
				Отбор = Новый Структура("ЭтоРеквизитТабличнойЧасти", Истина);
				ВидыКИТабличнойЧасти = УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеКонтактнойИнформацииНаФорме(Форма).Выгрузить(Отбор, "Вид");
				// @skip-check query-in-loop - Выполняется только в одной итерации, при первом появлении реквизита табличной части
				ИменаТабличныхЧастейПоВидамКИ = ИменаТабличныхЧастейПоВидамКИ(ВидыКИТабличнойЧасти, ИмяОбъектаМетаданных);
			КонецЕсли;
			
			ИмяТабличнойЧасти = ИменаТабличныхЧастейПоВидамКИ[СтрокаТаблицы.Вид];
			ТабличнаяЧастьФормы = Форма.Объект[ИмяТабличнойЧасти];
			Для Каждого СтрокаТабличнойЧастиФормы Из ТабличнаяЧастьФормы Цикл
				
				ИдентификаторСтроки = СтрокаТабличнойЧастиФормы.ПолучитьИдентификатор();
				СтрокаТабличнойЧастиФормы.ИдентификаторСтрокиТабличнойЧасти = ИдентификаторСтроки;
				
				СтрокаТабличнойЧасти = Объект[ИмяТабличнойЧасти][СтрокаТабличнойЧастиФормы.НомерСтроки - 1];
				СтрокаТабличнойЧасти.ИдентификаторСтрокиТабличнойЧасти = ИдентификаторСтроки;
				
				Значение = СтрокаТабличнойЧастиФормы[ИмяРеквизита + "Значение"];
				
				ПеренестиЗаписьКонтактнойИнформацииИзФормыВТаблицу(КонтактнаяИнформация, СтрокаТаблицы, Значение, ИдентификаторСтроки);
				
			КонецЦикла;
			
		Иначе
			
			Если СтрокаТаблицы.Вид.Родитель <> ГруппаВидовКонтактнойИнформации Тогда
				Продолжить;
			КонецЕсли;
			
			ПеренестиЗаписьКонтактнойИнформацииИзФормыВТаблицу(КонтактнаяИнформация, СтрокаТаблицы, СтрокаТаблицы.Значение);
			
		КонецЕсли;
		
	КонецЦикла;
	
	Возврат КонтактнаяИнформация;
	
КонецФункции

Процедура ПеренестиЗаписьКонтактнойИнформацииИзФормыВТаблицу(КонтактнаяИнформация, СтрокаТаблицы, Знач Значение, Знач ИдентификаторСтроки = Неопределено)
	
	Если ПустаяСтрока(Значение) Тогда
		Возврат;
	КонецЕсли;
	
	Если УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВXML(Значение) Тогда
		ОбъектКИ = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияВСтруктуруJSON(Значение, СтрокаТаблицы.Тип);
	Иначе
		ОбъектКИ = УправлениеКонтактнойИнформациейСлужебный.JSONВКонтактнуюИнформациюПоПолям(Значение, СтрокаТаблицы.Тип);
	КонецЕсли;
	
	Если Не УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияЗаполнена(ОбъектКИ) Тогда
		Возврат;
	КонецЕсли;
	
	СтрокаКонтактнойИнформации = КонтактнаяИнформация.Добавить();
	
	ДействуетС = ?(СтрокаТаблицы.Свойство("ДействуетС"), СтрокаТаблицы.ДействуетС, Неопределено);
	ЗаполнитьЗначенияСвойств(СтрокаКонтактнойИнформации, СтрокаТаблицы, "Вид,Тип");
	
	СтрокаКонтактнойИнформации.Представление = ОбъектКИ.Value;
	СтрокаКонтактнойИнформации.Значение      = УправлениеКонтактнойИнформациейСлужебный.СтруктураВСтрокуJSON(ОбъектКИ);
	
	Если УправлениеКонтактнойИнформациейСлужебныйПовтИсп.ДоступенМодульЛокализации() Тогда
		МодульУправлениеКонтактнойИнформациейЛокализация = ОбщегоНазначения.ОбщийМодуль("УправлениеКонтактнойИнформациейЛокализация");
		СтрокаКонтактнойИнформации.ЗначенияПолей = МодульУправлениеКонтактнойИнформациейЛокализация.КонтактнаяИнформацияИзJSONВXML(ОбъектКИ, СтрокаТаблицы.Тип);
	КонецЕсли;
	
	Если ЗначениеЗаполнено(ДействуетС) Тогда
		СтрокаКонтактнойИнформации.Дата    = ДействуетС;
	КонецЕсли;
	
	СтрокаКонтактнойИнформации.ИдентификаторСтрокиТабличнойЧасти = ИдентификаторСтроки;
	
КонецПроцедуры

// Виды контактной информации

Функция ПараметрыИзВидаКонтактнойИнформации(Знач ВидКонтактнойИнформации)
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
	"ВЫБРАТЬ ПЕРВЫЕ 1
	|	ВидыКонтактнойИнформации.Ссылка КАК Ссылка,
	|	ВидыКонтактнойИнформации.Родитель КАК Родитель,
	|	ВидыКонтактнойИнформации.ЭтоГруппа КАК ЭтоГруппа,
	|	ВидыКонтактнойИнформации.Наименование КАК Наименование,
	|	ВидыКонтактнойИнформации.ТолькоНациональныйАдрес КАК ТолькоНациональныйАдрес,
	|	ВидыКонтактнойИнформации.ВидПоляДругое КАК ВидПоляДругое,
	|	ВидыКонтактнойИнформации.ВключатьСтрануВПредставление КАК ВключатьСтрануВПредставление,
	|	ВидыКонтактнойИнформации.ЗапретитьРедактированиеПользователем КАК ЗапретитьРедактированиеПользователем,
	|	ВидыКонтактнойИнформации.Используется КАК Используется,
	|	ВидыКонтактнойИнформации.МожноИзменятьСпособРедактирования КАК МожноИзменятьСпособРедактирования,
	|	ВидыКонтактнойИнформации.ОбязательноеЗаполнение КАК ОбязательноеЗаполнение,
	|	ВидыКонтактнойИнформации.ПроверятьКорректность КАК ПроверятьКорректность,
	|	ВидыКонтактнойИнформации.РазрешитьВводНесколькихЗначений КАК РазрешитьВводНесколькихЗначений,
	|	ВидыКонтактнойИнформации.ВидРедактирования КАК ВидРедактирования,
	|	ВидыКонтактнойИнформации.РеквизитДопУпорядочивания КАК РеквизитДопУпорядочивания,
	|	ВидыКонтактнойИнформации.СкрыватьНеактуальныеАдреса КАК СкрыватьНеактуальныеАдреса,
	|	ВидыКонтактнойИнформации.ТелефонСДобавочнымНомером КАК ТелефонСДобавочнымНомером,
	|	ВидыКонтактнойИнформации.МаскаНомераТелефона КАК МаскаНомераТелефона,
	|	ВидыКонтактнойИнформации.ВводитьНомерПоМаске КАК ВводитьНомерПоМаске,
	|	ВидыКонтактнойИнформации.Тип КАК Тип,
	|	ВидыКонтактнойИнформации.ХранитьИсториюИзменений КАК ХранитьИсториюИзменений,
	|	ВидыКонтактнойИнформации.ИмяПредопределенногоВида КАК Имя,
	|	ВидыКонтактнойИнформации.МеждународныйФорматАдреса КАК МеждународныйФорматАдреса,
	|	ВидыКонтактнойИнформации.ОтображатьВсегда КАК ОтображатьВсегда
	|ИЗ
	|	Справочник.ВидыКонтактнойИнформации КАК ВидыКонтактнойИнформации
	|ГДЕ
	|	ВидыКонтактнойИнформации.Ссылка = &Ссылка";
	
	Запрос.УстановитьПараметр("Ссылка", ВидКонтактнойИнформации);
	
	РезультатЗапроса = Запрос.Выполнить().Выгрузить();
	
	Если РезультатЗапроса.Количество() = 0 Тогда
		ШаблонТекстаОшибки = НСтр("ru = 'При получении свойств контактной информации был передан неверный вид контактной информации. %1'");
		ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонТекстаОшибки , Строка(ВидКонтактнойИнформации));
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;
	
	Тип = РезультатЗапроса[0].Тип;
	
	ТекущиеПараметры = ОбщегоНазначения.СтрокаТаблицыЗначенийВСтруктуру(РезультатЗапроса[0]);
	ПараметрыВида = ОписаниеПараметровКонтактнойИнформации(Тип);
	ЗаполнитьЗначенияСвойств(ПараметрыВида, ТекущиеПараметры);
	
	Если Тип = Перечисления.ТипыКонтактнойИнформации.Адрес Тогда
		
		ЗаполнитьЗначенияСвойств(ПараметрыВида.НастройкиПроверки, ТекущиеПараметры, "ВключатьСтрануВПредставление,
		|ПроверятьКорректность,СкрыватьНеактуальныеАдреса,ТолькоНациональныйАдрес");
		
		Если УправлениеКонтактнойИнформациейСлужебныйПовтИсп.ДоступныМодулиРаботаСАдресами() Тогда
			МодульРаботаСАдресами = ОбщегоНазначения.ОбщийМодуль("РаботаСАдресами");
			МодульРаботаСАдресами.ДополнитьНастройкиПроверкиАдреса(ПараметрыВида, ВидКонтактнойИнформации);
		КонецЕсли;
		
	ИначеЕсли Тип = Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты Тогда
		ПараметрыВида.НастройкиПроверки.ПроверятьКорректность = ТекущиеПараметры.ПроверятьКорректность;
	ИначеЕсли Тип = Перечисления.ТипыКонтактнойИнформации.Телефон Тогда
		ПараметрыВида.НастройкиПроверки.ТелефонСДобавочнымНомером = ТекущиеПараметры.ТелефонСДобавочнымНомером;
		ПараметрыВида.НастройкиПроверки.МаскаНомераТелефона = ТекущиеПараметры.МаскаНомераТелефона;
		ПараметрыВида.НастройкиПроверки.ВводитьНомерПоМаске = ТекущиеПараметры.ВводитьНомерПоМаске;
	ИначеЕсли Тип = Перечисления.ТипыКонтактнойИнформации.Другое Тогда
		ПараметрыВида.ВидПоляДругое = ТекущиеПараметры.ВидПоляДругое;
	КонецЕсли;
	
	ПараметрыВида.Вид = РезультатЗапроса[0].Ссылка;
	
	Возврат ПараметрыВида;
	
КонецФункции

Функция НастройкиПроверкиПараметровКонтактнойИнформации(Знач ТипКонтактнойИнформации)
	
	НастройкиПроверки = Новый Структура;
	
	Если ТипКонтактнойИнформации =  Перечисления.ТипыКонтактнойИнформации.Адрес Тогда
		НастройкиПроверки.Вставить("ТолькоНациональныйАдрес",      Ложь);
		НастройкиПроверки.Вставить("ПроверятьКорректность",        Ложь);
		НастройкиПроверки.Вставить("ВключатьСтрануВПредставление", Ложь);
		НастройкиПроверки.Вставить("УказыватьОКТМО",               Ложь);
		НастройкиПроверки.Вставить("СкрыватьНеактуальныеАдреса",   Ложь); // устарело. Оставлено для обратной совместимости.
		НастройкиПроверки.Вставить("ПроверятьПоФИАС",              Истина); // устарело. Оставлено для обратной совместимости.
	ИначеЕсли ТипКонтактнойИнформации = Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты Тогда
		НастройкиПроверки = Новый Структура;
		НастройкиПроверки.Вставить("ПроверятьКорректность",        Ложь);
	ИначеЕсли ТипКонтактнойИнформации =  Перечисления.ТипыКонтактнойИнформации.Телефон Тогда
		НастройкиПроверки = Новый Структура;
		НастройкиПроверки.Вставить("ТелефонCДобавочнымНомером",    Истина);
		НастройкиПроверки.Вставить("ТелефонСДобавочнымНомером",    Истина);
		НастройкиПроверки.Вставить("ВводитьНомерПоМаске", Ложь);
		НастройкиПроверки.Вставить("МаскаНомераТелефона", "");
	КонецЕсли;
	
	Возврат НастройкиПроверки;

КонецФункции

Функция ОбъектВидаКонтактнойИнформации(Имя, ЭтоГруппа = Ложь)
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
	"ВЫБРАТЬ ПЕРВЫЕ 1
	|	ВидыКонтактнойИнформации.Ссылка КАК Ссылка
	|ИЗ
	|	Справочник.ВидыКонтактнойИнформации КАК ВидыКонтактнойИнформации
	|ГДЕ
	|	ВидыКонтактнойИнформации.ИмяПредопределенногоВида = &Имя
	|	И ВидыКонтактнойИнформации.ЭтоГруппа = &ЭтоГруппа";
	
	Запрос.УстановитьПараметр("Имя", Имя);
	Запрос.УстановитьПараметр("ЭтоГруппа", ЭтоГруппа);
	
	РезультатЗапроса = Запрос.Выполнить();
	Если Не РезультатЗапроса.Пустой() Тогда
		ВыборкаДетальныеЗаписи = РезультатЗапроса.Выгрузить();
		Ссылка = ВыборкаДетальныеЗаписи[0].Ссылка;
		Возврат Ссылка.ПолучитьОбъект();
	КонецЕсли;
	
	ИменаПредопределенных = Метаданные.Справочники.ВидыКонтактнойИнформации.ПолучитьИменаПредопределенных();
	ИмяПредопределенного  = ИменаПредопределенных.Найти(Имя);
	
	Если ИмяПредопределенного <> Неопределено Тогда
		Объект = Справочники.ВидыКонтактнойИнформации[Имя].ПолучитьОбъект();
		Объект.ИмяПредопределенногоВида = Имя;
		Возврат Объект;
	КонецЕсли;
	
	Если ЭтоГруппа Тогда
		НовыйЭлемент = Справочники.ВидыКонтактнойИнформации.СоздатьГруппу();
	Иначе
		НовыйЭлемент = Справочники.ВидыКонтактнойИнформации.СоздатьЭлемент();
	КонецЕсли;
	
	НовыйЭлемент.ИмяПредопределенногоВида = Имя;
	
	Возврат НовыйЭлемент;
	
КонецФункции

// Возвращает описание свойств контактной информации для переданного типа контактной информации.
// Полученная структура используется в обработчиках обновления при заполнении видов контактной информации 
// или при формировании параметров открытии формы ввода адреса или телефона для метода используемые в ОткрытьФормуКонтактнойИнформации.
// 
// Параметры:
//    ТипКонтактнойИнформации - ПеречислениеСсылка.ТипыКонтактнойИнформации - тип контактной информации.
//
// Возвращаемое значение:
//   Структура:
//     * Имя          - Строка - уникальное имя вида контактной информации.
//     * Наименование - Строка - наименование вида контактной информации.
//     * Вид - СправочникСсылка.ВидыКонтактнойИнформации - ссылка на вид контактной информации.
//                                                         Значение по умолчанию - СправочникСсылка.ВидыКонтактнойИнформации.ПустаяСсылка.
//     * Тип - ПеречислениеСсылка.ТипыКонтактнойИнформации - тип контактной информации.
//     * Группа - СправочникСсылка.ВидыКонтактнойИнформации
//              - Неопределено - ссылка на группу(родителя) элемента справочника.
//                               Значение по умолчанию - Неопределено.
//     * Используется - Булево - если Ложь, то вид контактной информации недоступен для использования пользователем.
//                               Такой вид не выводится в формах и списке видов контактной информации.
//                               Значение по умолчанию - Истина.
//     * МожноИзменятьСпособРедактирования - Булево - признак возможности изменения свойств вида контактной информации пользователем.
//                                                    Если Ложь, то в форме вида контактной информации свойства доступны
//                                                    только для просмотра. Значение по умолчанию - Ложь.
//     * ВидРедактирования - Строка - определят вид редактирования значения. Варианты: "ПолеВводаИДиалог", "ПолеВвода", "Диалог".
//                                    Если "Диалог", то форме выводится гиперссылка с представлением контактной
//                                    информации, по нажатию на которую, открывается форма соответствующего типа КИ.
//                                    Свойство применимо только для контактной информации с типом: Адрес, Телефон, Факс.
//                                    Если "ПолеВвода", то на форме выводится поле ввода.
//                                    Если "ПолеВводаИДиалог", то доступен ввод в поле и в форме соответствующего типа КИ.
//     * ХранитьИсториюИзменений     - Булево - признак возможности хранения истории контактной информации.
//                                              Хранение истории допускается, если признак ВидРедактирования = "Диалог".
//                                              Свойство применимо если табличная часть КонтактнаяИнформация
//                                              содержит реквизит ДействуетС. Значение по умолчанию - Ложь.
//     * ОбязательноеЗаполнение       - Булево - если Истина, то требуется обязательный ввод значения в поле контактной
//                                               информации. Значение по умолчанию - Ложь.
//     * РазрешитьВводНесколькихЗначений - Булево - признак возможности ввода нескольких значений для данного вида.
//                                                  Значение по умолчанию - Ложь.
//     * ЗапретитьРедактированиеПользователем - Булево - признак недоступности редактирования пользователем вида
//                                                       контактной информации. Значение по умолчанию - Ложь.
//     * МеждународныйФорматАдреса - Булево - признак международного формата адреса. 
//                                   Если Истина, то ввода всех адресов только в международном формате.
//                                   Значение по умолчанию - Ложь.
//     * ВидПоляДругое             - Строка - определяет внешний вид поля с типом Другое на форме. Варианты:
//                                            МногострочноеШирокое, ОднострочноеШирокое, ОднострочноеУзкое. Свойство
//                                            применимо только для контактной информации с типом: Другое. Для вида КИ с
//                                            типом Другое значение по умолчанию - "ОднострочноеШирокое", иначе пустая строка.
//     * РедактированиеТолькоВДиалоге - Булево - устарело. Следует использовать ВидРедактирования.
//                                               Если Истина, то форме выводится гиперссылка с представлением контактной
//                                               информации по нажатию на которую, открывается форма соответствующего
//                                               типа КИ. Свойство применимо только для контактной информации с типом:
//                                               Адрес, Телефон, Факс, ВебСтраница. Значение по умолчанию - Ложь.
//     * НастройкиПроверки - Неопределено - для типов Другое, ВебСтраница, Skype 
//                         - Структура - состав полей зависит от типа контактной информации: 
//       ** ТолькоНациональныйАдрес- Булево - для типа Адрес. Если Истина, то разрешается ввод только национальных
//                                                          адресов. Изменение страны у адреса не допускается.
//       ** ПроверятьКорректность - Булево - для типа Адрес. Если Истина, то для национальных адресов доступен ввод
//                                           только адресов с разбивкой по полям проходящих проверку по адресному классификатору.
//                                           Допускается ввод адресов других стран в свободной форме,
//                                           если свойство ТолькоНациональныйАдрес = Ложь.
//                                           Значение по умолчанию - Ложь.
//       ** ВключатьСтрануВПредставление - Булево - для типа Адрес. если Истина, то Наименование страны всегда
//                                                 добавляется в представление адреса, даже когда другие поля адреса пустые.
//                                                 Значение по умолчанию - Ложь.
//       ** УказыватьОКТМО - Булево - для типа Адрес. признак возможности ручного ввода кода ОКМТО в форме ввода адреса.
//       ** ПроверятьКорректность - Булево - для типа АдресЭлектроннойПочты. Если Истина, то запрещается пользователю ввод 
//                                           некорректный адрес электронной почты. Значение по умолчанию - Ложь.
//       ** ТелефонСДобавочнымНомером - Булево - для типа Телефон или Факс. Если Истина, то в форме ввода телефона
//                                               доступен ввод добавочного номера. Значение по умолчанию - Истина.
//
Функция ОписаниеПараметровКонтактнойИнформации(Знач ТипКонтактнойИнформации)
	
	ПараметрыВида = ОписаниеОбщихПараметровВидаКонтактнойИнформации();
	
	ПараметрыВида.Вставить("Вид", Справочники.ВидыКонтактнойИнформации.ПустаяСсылка());
	ПараметрыВида.Вставить("Порядок", Неопределено);
	ПараметрыВида.Вставить("Тип", ТипКонтактнойИнформации);
	ПараметрыВида.Вставить("МожноИзменятьСпособРедактирования",    Ложь);
	ПараметрыВида.Вставить("РедактированиеТолькоВДиалоге",         Ложь);  // устарело. Оставлено для обратной совместимости.
	ПараметрыВида.Вставить("ОбязательноеЗаполнение",               Ложь);
	ПараметрыВида.Вставить("РазрешитьВводНесколькихЗначений",      Ложь);
	ПараметрыВида.Вставить("ЗапретитьРедактированиеПользователем", Ложь);
	ПараметрыВида.Вставить("ХранитьИсториюИзменений",              Ложь);
	ПараметрыВида.Вставить("МеждународныйФорматАдреса",            Ложь);
	ПараметрыВида.Вставить("ИсправлятьУстаревшиеАдреса",           Ложь);
	ПараметрыВида.Вставить("ОтображатьВсегда",                     Истина);
	
	ВидПоляДругое = ?(ТипКонтактнойИнформации = Перечисления.ТипыКонтактнойИнформации.Другое,
		"ОднострочноеШирокое", "");
	
	Если ТипКонтактнойИнформации = Перечисления.ТипыКонтактнойИнформации.Адрес
		 Или ТипКонтактнойИнформации = Перечисления.ТипыКонтактнойИнформации.Факс
		 Или ТипКонтактнойИнформации = Перечисления.ТипыКонтактнойИнформации.Телефон Тогда
			ВидРедактирования = "ПолеВводаИДиалог";
	ИначеЕсли ТипКонтактнойИнформации = Перечисления.ТипыКонтактнойИнформации.ВебСтраница Тогда
			ВидРедактирования = "Диалог";
	Иначе
			ВидРедактирования = "ПолеВвода";
	КонецЕсли;
	
	ПараметрыВида.Вставить("ВидРедактирования", ВидРедактирования);
	ПараметрыВида.Вставить("ВидПоляДругое",     ВидПоляДругое);
	
	НастройкиПроверки = НастройкиПроверкиПараметровКонтактнойИнформации(ТипКонтактнойИнформации);
	
	ПараметрыВида.Вставить("НастройкиПроверки", НастройкиПроверки);
	Возврат ПараметрыВида;

КонецФункции

Функция ОписаниеОбщихПараметровВидаКонтактнойИнформации()
	
	ПараметрыВида = Новый Структура;
	ПараметрыВида.Вставить("Имя", "");
	ПараметрыВида.Вставить("Группа", Неопределено);
	ПараметрыВида.Вставить("Наименование", "");
	ПараметрыВида.Вставить("Используется", Истина);
	
	Возврат ПараметрыВида;
	
КонецФункции

// Конструктор описания страны мира. 
// 
// Параметры:
//   РезультатЗапроса - Структура - данные заполнения.
// 	 
// Возвращаемое значение:
//   Структура:
//    Код - Строка - числовой код страны по классификатору;
//    КодАльфа2 - Строка - двузначный буквенный код альфа-2 страны по классификатору;
//    КодАльфа3 - Строка - трехзначный буквенный код альфа-3 страны по классификатору;
//    Наименование - Строка - краткое наименование страны мира
//    НаименованиеПолное - Строка - полное наименование страны мира;
//    УчастникЕАЭС - Булево - страна является участником Евразийского экономического союза;
//    Неактуальный - Булево - помечена на удаление.
//
Функция ОписаниеСтраныМира(ДанныеЗаполнения)
	
	Результат = Новый Структура;
	Результат.Вставить("Код", "");
	Результат.Вставить("КодАльфа2", "");
	Результат.Вставить("КодАльфа3", "");
	Результат.Вставить("Наименование", "");
	Результат.Вставить("НаименованиеПолное", "");
	Результат.Вставить("МеждународноеНаименование", "");
	Результат.Вставить("УчастникЕАЭС", Ложь);
	Результат.Вставить("Неактуальный", Ложь);
	
	ЗаполнитьЗначенияСвойств(Результат, ДанныеЗаполнения);
	
	Возврат Результат
КонецФункции

// Страны ЕАЭС добавленные пользователем в справочник СтраныМира.
// 
// Возвращаемое значение:
//   см. СтраныУчастникиЕАЭС
// 
Функция ПользовательскиеСтраныЕАЭС() Экспорт
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ
		|	СтраныМира.Ссылка КАК Ссылка,
		|	СтраныМира.Наименование КАК Наименование,
		|	СтраныМира.Код КАК Код,
		|	СтраныМира.НаименованиеПолное КАК НаименованиеПолное,
		|	СтраныМира.КодАльфа2 КАК КодАльфа2,
		|	СтраныМира.МеждународноеНаименование КАК МеждународноеНаименование,
		|	СтраныМира.КодАльфа3 КАК КодАльфа3
		|ИЗ
		|	Справочник.СтраныМира КАК СтраныМира
		|ГДЕ
		|	СтраныМира.УчастникЕАЭС = ИСТИНА";
	
	СтраныЕАЭС = Запрос.Выполнить().Выгрузить();
	
	Возврат СтраныЕАЭС;
	
КонецФункции

Функция СформироватьТекстЗапроса(Знач ЕстьКолонкаИдентификаторСтрокиТабличнойЧасти, Знач ТекстЗапросаИсторическаяИнформация, Знач ЭтоОсновнойЯзык)
	
		ТекстЗапроса = "ВЫБРАТЬ
	|	КонтактнаяИнформация.Представление               КАК Представление,
	|	КонтактнаяИнформация.Значение                    КАК Значение,
	|	КонтактнаяИнформация.ЗначенияПолей               КАК ЗначенияПолей,
	|	КонтактнаяИнформация.НомерСтроки                 КАК НомерСтроки,
	|	&ДействуетС                                      КАК ДействуетС,
	|	&ЭтоИсторическаяКонтактнаяИнформация             КАК ЭтоИсторическаяКонтактнаяИнформация,
	|	КонтактнаяИнформация.Вид                         КАК Вид,
	|	&ИдентификаторСтрокиТабличнойЧасти               КАК ИдентификаторСтрокиТабличнойЧасти
	|ПОМЕСТИТЬ 
	|	КонтактнаяИнформация
	|ИЗ
	|	&ТаблицаКонтактнойИнформации КАК КонтактнаяИнформация
	|ИНДЕКСИРОВАТЬ ПО
	|	Вид
	|;////////////////////////////////////////////////////////////////////////////////
	|
	|ВЫБРАТЬ
	|	ВидыКонтактнойИнформации.Ссылка                       КАК Вид,
	|ВЫБОР
	|	КОГДА ВидыКонтактнойИнформации.ИмяПредопределенногоВида <> """"
	|	ТОГДА ВидыКонтактнойИнформации.ИмяПредопределенногоВида
	|	ИНАЧЕ ВидыКонтактнойИнформации.ИмяПредопределенныхДанных
	|КОНЕЦ КАК ИмяПредопределенногоВида,
	|	ВидыКонтактнойИнформации.ИмяПредопределенныхДанных КАК ИмяПредопределенныхДанных,
	|	ВидыКонтактнойИнформации.Тип                          КАК Тип,
	|	ВидыКонтактнойИнформации.ОтображатьВсегда             КАК ОтображатьВсегда,
	|	ВидыКонтактнойИнформации.ОбязательноеЗаполнение       КАК ОбязательноеЗаполнение,
	|	ВидыКонтактнойИнформации.ВидПоляДругое                КАК ВидПоляДругое,
	|	ВидыКонтактнойИнформации.РазрешитьВводНесколькихЗначений КАК РазрешитьВводНесколькихЗначений,
	|	ВидыКонтактнойИнформации.Наименование КАК ПредставлениеНаОсновномЯзыке,
	|	ВидыКонтактнойИнформации.Наименование КАК Наименование,
	|	ВидыКонтактнойИнформации.ХранитьИсториюИзменений      КАК ХранитьИсториюИзменений,
	|	ВидыКонтактнойИнформации.ВидРедактирования            КАК ВидРедактирования,
	|	ВидыКонтактнойИнформации.ЭтоГруппа                    КАК ЭтоРеквизитТабличнойЧасти,
	|	ВидыКонтактнойИнформации.РеквизитДопУпорядочивания    КАК РеквизитДопУпорядочивания,
	|	ВидыКонтактнойИнформации.МеждународныйФорматАдреса    КАК МеждународныйФорматАдреса,
	|	ВидыКонтактнойИнформации.ВводитьНомерПоМаске  КАК ВводитьНомерПоМаске,
	|	ВидыКонтактнойИнформации.МаскаНомераТелефона    КАК МаскаНомераТелефона,
	|	ЕСТЬNULL(КонтактнаяИнформация.ЭтоИсторическаяКонтактнаяИнформация, ЛОЖЬ)    КАК ЭтоИсторическаяКонтактнаяИнформация,
	|	ЕСТЬNULL(КонтактнаяИнформация.Представление, """")    КАК Представление,
	|	ЕСТЬNULL(КонтактнаяИнформация.ЗначенияПолей, """")    КАК ЗначенияПолей,
	|	ЕСТЬNULL(КонтактнаяИнформация.Значение, """")         КАК Значение,
	|	ЕСТЬNULL(КонтактнаяИнформация.ДействуетС, 0)          КАК ДействуетС,
	|	ЕСТЬNULL(КонтактнаяИнформация.НомерСтроки, 0)         КАК НомерСтроки,
	|	ЕСТЬNULL(КонтактнаяИнформация.ИдентификаторСтрокиТабличнойЧасти, 0)    КАК ИдентификаторСтрокиТабличнойЧасти,
	|	ВЫРАЗИТЬ("""" КАК СТРОКА(200))                        КАК ИмяРеквизита,
	|	ВЫРАЗИТЬ("""" КАК СТРОКА(200))                        КАК ИмяРеквизитаКомментарий,
	|	ВидыКонтактнойИнформации.ПометкаУдаления              КАК ПометкаУдаления,
	|	ВЫРАЗИТЬ("""" КАК СТРОКА)                             КАК Комментарий
	|ИЗ
	|	Справочник.ВидыКонтактнойИнформации КАК ВидыКонтактнойИнформации
	|ЛЕВОЕ СОЕДИНЕНИЕ
	|	КонтактнаяИнформация КАК КонтактнаяИнформация
	|ПО
	|	ВидыКонтактнойИнформации.Ссылка = КонтактнаяИнформация.Вид
	|ГДЕ
	|	ВидыКонтактнойИнформации.Используется
	|	И ЕСТЬNULL(ВидыКонтактнойИнформации.Родитель.Используется, ИСТИНА)
	|	И (
	|		ВидыКонтактнойИнформации.Родитель = &ГруппаВидовКИ
	|		ИЛИ ВидыКонтактнойИнформации.Родитель.Родитель = &ГруппаВидовКИ)
	|	И ВидыКонтактнойИнформации.Ссылка НЕ В (&СкрываемыеВиды)
	|УПОРЯДОЧИТЬ ПО
	|	ВидыКонтактнойИнформации.Ссылка ИЕРАРХИЯ
	|";
		
	СуффиксТекущегоЯзыка = ОбщегоНазначения.СуффиксЯзыкаТекущегоПользователя();
		
	Если СуффиксТекущегоЯзыка <> Неопределено Тогда
		
		Если ЗначениеЗаполнено(СуффиксТекущегоЯзыка) Тогда
			МодульМультиязычностьСервер = ОбщегоНазначения.ОбщийМодуль("МультиязычностьСервер");
			МодульМультиязычностьСервер.ИзменитьПолеЗапросаПодТекущийЯзык(ТекстЗапроса, "ВидыКонтактнойИнформации.Наименование КАК Наименование");
		КонецЕсли;
		
	Иначе
		
		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "ВидыКонтактнойИнформации.Наименование КАК Наименование", 
			"ВЫРАЗИТЬ(ЕСТЬNULL(ВидыКонтактнойИнформацииПредставления.Наименование, ВидыКонтактнойИнформации.Наименование) КАК СТРОКА(150)) КАК Наименование");
		
		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "ГДЕ", "ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВидыКонтактнойИнформации.Представления КАК ВидыКонтактнойИнформацииПредставления
		|ПО ВидыКонтактнойИнформацииПредставления.Ссылка = ВидыКонтактнойИнформации.Ссылка
		|	И ВидыКонтактнойИнформацииПредставления.КодЯзыка = &КодЯзыка
		|ГДЕ");
		
	КонецЕсли;
	
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИдентификаторСтрокиТабличнойЧасти",
		?(ЕстьКолонкаИдентификаторСтрокиТабличнойЧасти,
		"ЕСТЬNULL(КонтактнаяИнформация.ИдентификаторСтрокиТабличнойЧасти, 0)",
		"0"));
	
	Если ТекстЗапросаИсторическаяИнформация Тогда
		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ДействуетС", "КонтактнаяИнформация.ДействуетС");
		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ЭтоИсторическаяКонтактнаяИнформация", "КонтактнаяИнформация.ЭтоИсторическаяКонтактнаяИнформация");
	Иначе
		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ДействуетС", "0");
		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ЭтоИсторическаяКонтактнаяИнформация", "ЛОЖЬ");
	КонецЕсли;
	
	Возврат ТекстЗапроса;
	
КонецФункции

// Восстановление пароля

// Имя реквизиты для восстановления пароля
//
// Параметры:
//  КонтактнаяИнформация - ДанныеФормыКоллекция
// 
// Возвращаемое значение:
//  Строка - имя реквизита на форме с электронной почтой для восстановления.
//
Функция ИмяРеквизитыДляВосстановленияПароля(Форма, АдресЭлектроннойПочты, ТипИлиВидEmailПользователя)
	
	ИмяРеквизитаДляВосстановленияПароля = "";
	
	ОписаниеПочты = СтрокаОписанияПочтыДляВосстановленияПароляИзДанныхФормы(
		Форма, ТипИлиВидEmailПользователя, АдресЭлектроннойПочты);
	
	Если ОписаниеПочты = Неопределено Тогда
		// Первая почта будет для восстановления
		ОписаниеПочты = СтрокаОписанияПочтыДляВосстановленияПароляИзДанныхФормы(
			Форма, ТипИлиВидEmailПользователя);
	КонецЕсли;
	
	Если ОписаниеПочты <> Неопределено Тогда
		ИмяРеквизитаДляВосстановленияПароля = ОписаниеПочты.ИмяРеквизита;
	КонецЕсли;
	
	Возврат ИмяРеквизитаДляВосстановленияПароля;
	
КонецФункции

Процедура УстановитьДействияДляСтатическихЭлементов(Форма, СтрокаКИ, ИмяЭлементаДляРазмещения)

	Элемент = Форма.Элементы[СтрокаКИ.ИмяРеквизита];
	Тип = СтрокаКи.Тип;

	ПараметрыКонтактнойИнформации = ПараметрыКонтактнойИнформацииФормы(Форма.ПараметрыКонтактнойИнформации,
		ИмяЭлементаДляРазмещения);
	ОбработкаНавигационнойСсылки = ПараметрыКонтактнойИнформации.ОбработкаНавигационнойСсылки;

	Если СтрокаКИ.ВидРедактирования = "Диалог" И СтрокаКИ.Тип = Перечисления.ТипыКонтактнойИнформации.Адрес 
		И Элемент.Вид = ВидПоляФормы.ПолеНадписи Тогда

	Если НЕ ЗначениеЗаполнено(Элемент.ПолучитьДействие("Нажатие")) Тогда
		Элемент.УстановитьДействие("Нажатие", "Подключаемый_КонтактнаяИнформацияПриНажатии");
	КонецЕсли;

	ИначеЕсли Тип = Перечисления.ТипыКонтактнойИнформации.ВебСтраница И ОбработкаНавигационнойСсылки И Элемент.Вид = ВидПоляФормы.ПолеНадписи Тогда

		Если Не ЗначениеЗаполнено(Элемент.ПолучитьДействие("ОбработкаНавигационнойСсылки")) Тогда
			Элемент.УстановитьДействие("ОбработкаНавигационнойСсылки", "Подключаемый_КонтактнаяИнформацияОбработкаНавигационнойСсылки");
		КонецЕсли;

	ИначеЕсли Элемент.Вид = ВидПоляФормы.ПолеВвода Тогда 

		Если Не ЗначениеЗаполнено(Элемент.ПолучитьДействие("Очистка")) Тогда
			Элемент.УстановитьДействие("Очистка", "Подключаемый_КонтактнаяИнформацияОчистка");
		КонецЕсли;

		Если Тип = Перечисления.ТипыКонтактнойИнформации.Адрес Тогда
			Если Не ЗначениеЗаполнено(Элемент.ПолучитьДействие("Автоподбор")) Тогда
				Элемент.УстановитьДействие("Автоподбор", "Подключаемый_КонтактнаяИнформацияАвтоподбор");
			КонецЕсли;
			Если Не ЗначениеЗаполнено(Элемент.ПолучитьДействие("ОбработкаВыбора")) Тогда
				Элемент.УстановитьДействие("ОбработкаВыбора", "Подключаемый_КонтактнаяИнформацияОбработкаВыбора");
			КонецЕсли;
		КонецЕсли;

	КонецЕсли;
	
	// Редактирование в диалоге
	Если ДляТипаКонтактнойИнформацииДоступноРедактированиеВДиалоге(Тип) И Элемент.Вид = ВидПоляФормы.ПолеВвода
		И Не СтрокаКИ.ВидРедактирования = "ПолеВвода" Тогда

		ДоступенВыбор = Не СтрокаКИ.ПометкаУдаления И СтрокаКИ.ВидРедактирования <> "ПолеВвода";

		Если ДоступенВыбор И Не Форма.ТолькоПросмотр Тогда
			Элемент.КнопкаВыбора = Истина;
			Если Не ЗначениеЗаполнено(Элемент.ПолучитьДействие("НачалоВыбора")) Тогда
				Элемент.УстановитьДействие("НачалоВыбора", "Подключаемый_КонтактнаяИнформацияНачалоВыбора");
			КонецЕсли;
		Иначе
			Элемент.КнопкаВыбора   = Ложь;
			Если ЗначениеЗаполнено(Форма[СтрокаКИ.ИмяРеквизита]) Тогда
				Элемент.КнопкаОткрытия = Истина;
				Если Не ЗначениеЗаполнено(Элемент.ПолучитьДействие("Открытие")) Тогда
					Элемент.УстановитьДействие("Открытие", "Подключаемый_КонтактнаяИнформацияПриНажатии");
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;

	КонецЕсли;

	Если Не ЗначениеЗаполнено(Элемент.ПолучитьДействие("ПриИзменении")) Тогда
		Элемент.УстановитьДействие("ПриИзменении", "Подключаемый_КонтактнаяИнформацияПриИзменении");
	КонецЕсли;
	
	Если ДляТипаКонтактнойИнформацииЕстьПолеКомментарий(Тип, ОбработкаНавигационнойСсылки) Тогда
		ИмяЭлементаКомментарий = "Комментарий" + СтрокаКИ.ИмяРеквизита;
		Если Форма.Элементы.Найти(ИмяЭлементаКомментарий) <> Неопределено Тогда
			Если Не ЗначениеЗаполнено(Форма.Элементы[ИмяЭлементаКомментарий].ПолучитьДействие("ПриИзменении")) Тогда
				Форма.Элементы[ИмяЭлементаКомментарий].УстановитьДействие("ПриИзменении", "Подключаемый_КонтактнаяИнформацияПриИзменении");
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;

КонецПроцедуры

// Описание дополнительных параметров вывода контактной информации
// 
// Параметры:             
//   ОписаниеКоманд   - см. ОписаниеКоманд 
//   ОтображатьИконки - Булево
//   РазмещеныНаФорме - Соответствие из КлючИЗначение:
//     * Ключ - СправочникСсылка.ВидыКонтактнойИнформации
//     * Значение - Булево
//                - Неопределено
//   РазрешитьДобавлениеПолей - Булево
//   ИсключаемыеВиды  - Массив
//                    - Неопределено
//   СкрываемыеВиды   - Массив
//                    - Неопределено
// 	
// Возвращаемое значение:
//  Структура:
//    * ОписаниеКоманд   - см. ОписаниеКоманд 
//    * ОтображатьИконки - Булево
//    * РазмещеныНаФорме - Соответствие из КлючИЗначение:
//        ** Ключ - СправочникСсылка.ВидыКонтактнойИнформации
//        ** Значение - Булево
//                    - Неопределено
//    * РазрешитьДобавлениеПолей - Булево
//    * ИсключаемыеВиды  - Массив
//                       - Неопределено
//    * СкрываемыеВиды   - Массив
//                       - Неопределено
//    * ШиринаПоляКомментарий - Число
//    * ПоложениеКнопкиДобавить - ГоризонтальноеПоложениеЭлемента
//
Функция ДополнительныеПараметрыВыводаКонтактнойИнформации(ОписаниеКоманд, ОтображатьИконки, РазмещеныНаФорме,
	РазрешитьДобавлениеПолей, ИсключаемыеВиды, СкрываемыеВиды) 

	ДополнительныеПараметры = Новый Структура;
	ДополнительныеПараметры.Вставить("ОписаниеКоманд",           ОписаниеКоманд);
	ДополнительныеПараметры.Вставить("ОтображатьИконки",         ОтображатьИконки);
	ДополнительныеПараметры.Вставить("РазмещеныНаФорме",         РазмещеныНаФорме);
	ДополнительныеПараметры.Вставить("РазрешитьДобавлениеПолей", РазрешитьДобавлениеПолей);
	ДополнительныеПараметры.Вставить("ИсключаемыеВиды",          ИсключаемыеВиды);
	ДополнительныеПараметры.Вставить("СкрываемыеВиды",           СкрываемыеВиды);
	ДополнительныеПараметры.Вставить("ШиринаПоляКомментарий",    30);
	ДополнительныеПараметры.Вставить("ПоложениеКнопкиДобавить", ГоризонтальноеПоложениеЭлемента.Лево);
	
	Возврат ДополнительныеПараметры;

КонецФункции

Функция НастройкиПодсистемы(ВладелецКонтактнойИнформации)
	
	Настройки = Новый Структура;
	Настройки.Вставить("ОтображатьИконки", Ложь);
	Настройки.Вставить("ОписаниеКоманд", ОписаниеКоманд());
	Настройки.Вставить("ПоложениеКнопкиДобавить", ГоризонтальноеПоложениеЭлемента.Лево);
	Настройки.Вставить("ШиринаПоляКомментарий", 30);
	
	УправлениеКонтактнойИнформациейПереопределяемый.ПриОпределенииНастроек(Настройки);
	
	Возврат Настройки;
	
КонецФункции

// Определяет наличие кнопки в группах контактной информации
// 
// Параметры:
//   Группа - ГруппаФормы
//          - ЭлементыФормы
//   ЭтоГруппаСтроки - Булево - если Истина, то выполняется поиск кнопки среди элементов внутри группы
// 
// Возвращаемое значение:
//   Булево
//
Функция ЕстьКнопкаКонтактнойИнформации(Группа, ЭтоГруппаСтроки)

	Если ЭтоГруппаСтроки Тогда  
		Если ТипЗнч(Группа) = Тип("ГруппаФормы") Тогда
			Для Каждого ЭлементГруппы Из Группа.ПодчиненныеЭлементы Цикл
				Если ЭлементГруппы.Вид = ВидКнопкиФормы.ОбычнаяКнопка Тогда
					Возврат Истина;
				КонецЕсли;
			КонецЦикла;
		КонецЕсли;
	Иначе
		Для Каждого ГруппаПоля Из Группа Цикл
			Если ТипЗнч(ГруппаПоля) <> Тип("ГруппаФормы") Тогда
				Продолжить;
			КонецЕсли;
			Для Каждого ЭлементГруппы Из ГруппаПоля.ПодчиненныеЭлементы Цикл
				Если ЭлементГруппы.Вид = ВидКнопкиФормы.ОбычнаяКнопка Тогда
					Возврат Истина;
				КонецЕсли;
			КонецЦикла;
		КонецЦикла;
	КонецЕсли;
	
	Возврат Ложь;

КонецФункции

// Возвращает картинку, иллюстрирующую тип контактной информации
//
// Параметры:
//  ТипКонтактнойИнформации	 - ПеречислениеСсылка.ТипыКонтактнойИнформации
// 
// Возвращаемое значение:
//  Картинка - картинка, иллюстрирующая тип контактной информации
//
Функция КартинкаТипаКонтактнойИнформации(ТипКонтактнойИнформации)
	
	Возврат УправлениеКонтактнойИнформациейСлужебныйПовтИсп.КартинкиТиповКонтактнойИнформации().Получить(ТипКонтактнойИнформации);
		
КонецФункции

// Проверяет предполагаемое наличие поля "Комментарий" для типа контактной информации
//
// Параметры:
//  ТипКонтактнойИнформации	     - ПеречислениеСсылка.ТипыКонтактнойИнформации
//  ОбработкаНавигационнойСсылки - Булево
// 
// Возвращаемое значение:
//  Булево - признак наличия поля комментария на форме
//
Функция ДляТипаКонтактнойИнформацииЕстьПолеКомментарий(ТипКонтактнойИнформации, ОбработкаНавигационнойСсылки)
	
	Если ТипКонтактнойИнформации = Перечисления.ТипыКонтактнойИнформации.Адрес 
		ИЛИ ТипКонтактнойИнформации = Перечисления.ТипыКонтактнойИнформации.Другое 
		ИЛИ (ТипКонтактнойИнформации = Перечисления.ТипыКонтактнойИнформации.ВебСтраница И ОбработкаНавигационнойСсылки) Тогда
		Возврат Ложь;
	Иначе
		Возврат Истина;
	КонецЕсли;
	
КонецФункции

// Определяет наличие гиперссылки
// 
// Параметры:
//  Элемент - ГруппаФормы
//          - ПолеФормы
// 
// Возвращаемое значение:
//  Булево
//
Функция ЕстьГиперссылка(Элемент)

	Если ТипЗнч(Элемент) = Тип("ГруппаФормы") Тогда
		Для Каждого ЭлементГруппы Из Элемент.ПодчиненныеЭлементы Цикл
			Если ЭлементГруппы.Вид = ВидПоляФормы.ПолеНадписи Тогда
				Возврат Истина;
			КонецЕсли;
		КонецЦикла;
	ИначеЕсли ТипЗнч(Элемент) = Тип("ПолеФормы") И Элемент.Вид = ВидПоляФормы.ПолеНадписи Тогда
		Возврат Истина;
	КонецЕсли;

	Возврат Ложь;

КонецФункции

#КонецОбласти